传递给Action代表?

时间:2016-03-18 03:45:08

标签: c# delegates

我正在尝试使用在我定义的委托之外定义的引用(我正在处理的简化版本):

private void DoStuff(int objectKey)
{
    MyObject myObject;

    if (this.concurrentDictionary.TryRemove(objectKey, out myObject))
    {
        Action<IList<IEvent>> eventsCompletedDelegate (eventList) =>
        {
            // Do work ...

            myObject.DoSomething();
        };

        ExecuteStuffAsync(eventsCompletedDelegate);
    }
}

问题是eventsCompletedDelegate是异步执行的(在调用ExecuteStuffAsync之后的某个时间)。我希望能够从闭包中访问myObject,但是在调用委托时,将释放本地myObject引用。有没有办法将myObject传递给委托,以便在调用委托时它仍然可用?

2 个答案:

答案 0 :(得分:-1)

不,myObject不会被处置,因为来自eventsCompletedDelegate(variable capture)的引用。这是内存泄漏的常见原因。

答案 1 :(得分:-1)

如果您创建myObject的对象引用x并将其传递给您的操作,则您的“复制”引用x仍将在回调中可用,并且不会被垃圾回收。 / p>

这将输出“达到DoSomething 1”。

但是,如果处理引用,如Enigmativity所述,这也将修改复制的引用,调用dispos。这将改为输出“达到DoSomething 0”。除了确保在调用回调之前不调配myObject之外,没有办法阻止这种情况。

void Main()
{
    concurrentDictionary[1] = new MyObject(1);
    DoStuff(1);
}

private ConcurrentDictionary<int, MyObject> concurrentDictionary = 
    new ConcurrentDictionary<int, UserQuery.MyObject>();

private async void DoStuff(int objectKey)
{
    MyObject myObject;

    if (this.concurrentDictionary.TryRemove(objectKey, out myObject))
    {
        Action<MyObject> eventsCompletedDelegate = (objectRef) =>
        {
            objectRef.DoSomething();
        };
        var x = myObject;
        // myObject.Dispose(); // will set _id to 0 if called
        myObject = null;

        await ExecuteStuffAsync(() => eventsCompletedDelegate(x));
    }
}

public async Task ExecuteStuffAsync(Action callback)
{
    await Task.Delay(1000);
    callback();
}


public class MyObject : IDisposable
{
    private int _id;    
    public MyObject(int id)
    {
        _id = id;   
    }

    public void Dispose() { _id = 0; }

    public void DoSomething()
    {
        Console.WriteLine("reached DoSomething " + _id);
    }
}