在GC处置之前使用事件的C#重新引用对象,Ergo自动依赖模式和内存/ CPU高效集合

时间:2010-09-07 20:11:12

标签: c# events garbage-collection

我认为这将是一个有趣的模式。对象集合存储在管理器类中。当不需要对象时,它将从集合中删除。如果再次需要它,并且GC尚未处理它,则使用弱事件轮询现有对象的实例。例如:

class Manager
{
    //--- Events ---

    public event SearchingForInstanceEventHandler SearchingForInstance;


    //--- Fields ---

    List<OneOfMany> _many = new List<OneOfMany>();


    //--- Constructors ---

    public Manager()
    {
        // Create several OneOfMany instances.
        _many.Add(new OneOfMany(this, "C:\file1.txt"));
        _many.Add(new OneOfMany(this, "C:\file2.txt"));
        _many.Add(new OneOfMany(this, "C:\file3.txt"));

        // Erase the strong references to one or more OneOfMany instances.
        _many.Clear();

        // Attempt to find and reuse a previously generated instance, if the GC hasn't reclaimed it.
        SearchingForInstanceEventArgs e = new SearchingForInstanceEventArgs("C:\file2.txt");
        OnSearchingForInstance(e);

        OneOfMany oneOfMany = e.OneOfMany;

        // If a previously generated instance does not exist or has already been reclaimed by the GC, create a new one.
        if (oneOfMany == null)
            oneOfMany = new OneOfMany(this, "C:\file2.txt");

        // Store a reference to it while it is needed.
        _many.Add(e.OneOfMany);
    }


    //--- Protected Methods ---

    protected virtual void OnSearchingForInstance(SearchingForInstanceEventArgs e)
    {
        if (SearchingForInstance != null)
            SearchingForInstance(this, e);
    }
}

class OneOfMany
{
    //--- Fields ---

    string _key;

    Manager _manager;


    //--- Constructors ---

    public OneOfMany(Manager manager, string key)
    {
        _manager = manager;
        _key = key;

        _manager.SearchingForInstance += new SearchingForInstanceEventHandler(_manager_SearchingForInstance);

        // INSERT HERE: Long process generating much data (worth reusing if still exists in memory, and worth freeing if not needed)
    }


    //--- _manager Event Handlers ---

    void _manager_SearchingForInstance(object sender, SearchingForInstanceEventArgs e)
    {
        // If this is the instance the manager is searching for, return a reference to this.
        if (e.Key == _key)
            e.OneOfMany = this;
    }
}

class SearchingForInstanceEventArgs : EventArgs
{
    //--- Public Constructors ---

    public SearchingForInstanceEventArgs(string key)
    {
        Key = key;
    }


    //--- Public Properties ---

    public string Key { get; private set; }

    public OneOfMany OneOfMany{ get; set; }
}

delegate void SearchingForInstanceEventHandler(object sender, SearchingForInstanceEventArgs e);

这可用于利用GC尚未处理的内存,并且可以使用GC自动管理依赖项。例如,如果类OneOfMany引用其他OneOfMany实例(并且依赖于它们),则可以通过查询所需实例(具有事件)来添加新引用(即依赖项),并且GC将自动删除实例不再依赖。这与将OneOfMany的所有实例存储在集合中并查询集合以查找所需的依赖项的现有实例,并且必须遍历依赖树以手动删除非根的依赖项形成对比。

但是,我对此问题的关注是,如果在GC运行时实例在GC中重新生根?可以在GC谴责OneOfMany的时间和它处理它的时间之间制作一个关于OneOfMany的GC根源参考吗?如果没有,GC可以与此模式同步吗?

编辑:如果订阅该事件的当前方法不弱,则将其替换为较弱的方法。

1 个答案:

答案 0 :(得分:0)

我不确定为什么我要标记为Accepted的答案已被删除,但答案是这样的:

由于强引用可以从弱引用中任意提取,因此OP中的代码应该可以工作,假设不使用经过测试的缓存库。

以前待定的接受答案海报: 对不起,通过重新root我的意思是重新锚定。而且,谢谢,我没有意识到对象的复活。

相关问题