2011-02-24 44 views
3

我正在开发一个GUI应用程序,它非常依赖Action<>委托来定制我们的UI工具的行为。我想知道我们这样做的方式是否有任何潜在的问题,例如实现是否保持对捕获变量的引用,声明委托等的类实例?如何在C#中正确释放匿名代理/关闭?

假设我们有这个类MapControl,它包装了一个有状态的GUI控件。该地图具有不同种类的工具(绘图,选择等),由ITool界面表示。您可以使用StartTool()设置该工具,但一次只能有一个工具处于活动状态,因此当设置了另一个工具时,前一个工具将使用StopTool()停止。当工具停止时,执行调用者指定的回调委托。

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; 
    } 
} 

在应用程序的ViewModel类我们设置这样一些工具:

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); 
     }); 
    } 
} 

在我们的例子中ViewModel类连接到一个WPF应用程序的主窗口,并且只能有一个实例ViewModel在应用程序生命周期内。如果情况不是这样,它会改变什么吗?宣布代表的类会更短暂吗?

我的问题是,我是否正确处置了回调委托?是否有任何情况下,这可能导致内存膨胀通过坚持引用它不应该?

更一般地说,处置匿名代表的安全和正确的方式是什么?

回答

2

恕我直言,这是好的,你没有坚持任何引用你不需要。清除StopTool中的引用后,您不再持有它们。

+0

我同意,我没有看到有理由这样做。我想将所有本地参考变量设置为空:P – vtortola 2011-02-24 10:13:13

+0

不完全正确。如果在StartTool的上下文中没有调用StopTool,则将这些引用设置为null是正确的。 – 2011-02-24 10:14:23

+0

@fencliff:如果我的回答对你有帮助,请好好接受它。 – 2011-02-24 15:38:45

0

我觉得更恰当的方法是:

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

是否有任何理由这样做?根据MSDN,Delegate.Remove返回null,如果第一个参数为null,那么它应该等同于OP所做的。 – 2011-02-24 10:17:57

2

你正在做的罚款取出参考方法的方式。


还有一件事你问:

我的问题是,我在配置回调代表的正确?

您不需要配置方法(或指向方法的指针),只有类。

0

如果您想确保正确处理所有未使用的对象,我建议您使用像CLR Profiler这样的工具,以便您可以全面了解应用程序如何分配/释放内存。