开发者

How to release anonymous delegates / closures correctly in C#?

I'm working on a GUI application, which relies heavily on Action<> delegates to customize behavior of our UI tools. I'm wondering if the way we are doing this has any potential issues, e.g. whether the implementation keeps references to captured variables, class instances that declare the delegates etc?

So let's say we have this class MapControl, which wraps a stateful GUI control. The map has different kinds of tools (Drawing, Selection, etc.), represented by ITool interface. You can set the tool with StartTool(), but you can only have one tool active at a time, so when another tool is set previous one is stopped using StopTool(). When tool is stopped, a caller-specified callback delegate is executed.

public class MapControl
{
    ITool _currentTool;
    Action<IResult> _onComplete;

    public void StartTool(ToolEnum tool, Action<IResult> onComplete) {

        //If tool is active, stop it first
        if (_currentTool != null) StopTool();

        _onComplete = onComplete;

        //Creates a tool class, etc.
        _currentTool = CreateTool(tool) as ITool;
    }

    public void StopTool() {

        //Execute callback delegate
        IResult result = _currentTool.GetResult();
        if (_onComplete != null)
            _onComplete(result);

        //Nix the references to callback and tool
        _onComplete = null;
        _currentTool = null;
    }
}

In the application's 开发者_开发百科ViewModel class we set some tool like this:

class ViewModel
{
    private MapControl _mapControl = new MapControl();
    public void SetSomeTool() 
    {
        //These variables will be captured in the closure
        var someClassResource = this.SomeClassResource;
        var someLocalResource = new object();

        //Start tool, specify callback delegate as lambda
        _mapControl.StartTool(ToolEnum.SelectTool, (IResult result) => {

            //Do something with result and the captured variables
            someClassResource.DoSomething(result, someLocalResource);
        });
    }
}

In our case the ViewModel class is attached to the main window of a WPF application, and there can only be one instance of ViewModel during the application lifetime. Would it change anything if this weren't the case, and the classes which declare the delegates would be more transient?

My question is, am I disposing of the callback delegates correctly? Are there any scenarios, where this can cause memory bloat by holding on to references it shouldn't?

More generally, what's the safe and correct way of disposing anonymous delegates?


IMHO, it is ok and you are not holding on to any references you don't need. With clearing the references in StopTool you no longer hold them.


You are doing fine with removing the Reference to methods that way.


One more thing you asked:

My question is, am I disposing of the callback delegates correctly?

You don't dispose methods (or pointers to methods for that matter), only classes.


I think a more proper way would be:

_onComplete = (Action<IResult>)Delegate.Remove(null, _onComplete);


If you want to make sure you are disposing correctly of all unused objects, I'd suggest you use tools like the CLR Profiler so that you can have a complete view of how your application is allocating/freeing memory.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜