如果我想做一些“火和忘记”的一些代码,但还是要确保我的内存被清理(每
Why does asynchronous delegate method require calling EndInvoke?),以下是否会达到这个目标?
Action myAction = () => LongRunTime(); myAction.BeginInvoke(myAction.EndInvoke,null);
我已经环顾四周,但没有看到这种模式在任何地方使用.相反,人们使用annonomoyus方法作为其回调(例如The proper way to end a BeginInvoke?)或者它们定义了一个实际的回调方法.由于我还没有看到别人这样做,所以它让我觉得它不起作用,否则就是一个坏主意.
谢谢!
解决方法
使用方法组转换而不是委托是正确的,EndInvoke仍将在您的Action上被调用.没有别的事情要做,因为这是一场火灾,忘了电话.
不幸的是,由于Action是一个委托,我们不能在BCL的某个类中添加一个断点,所以直接无可辩驳地证明EndInvoke是非常有用的.
该代码将(定期)检查由BeginInvoke返回的IAsyncResult的一些私有字段,这似乎跟踪EndInvoke是否已被调用:
public partial class MainWindow : Window { private Timer _timer = new Timer(TimerCallback,null,100,100); private static IAsyncResult _asyncResult; public MainWindow() { InitializeComponent(); } static void LongRunTime() { Thread.Sleep(1000); } void Window_Loaded(object sender,RoutedEventArgs args) { Action myAction = () => LongRunTime(); _asyncResult = myAction.BeginInvoke(myAction.EndInvoke,null); } static void TimerCallback(object obj) { if (_asyncResult != null) { bool called = ((dynamic)_asyncResult).EndInvokeCalled; if (called) { // Will hit this breakpoint after LongRuntime has completed Debugger.Break(); _asyncResult = null; } } } }
我已经使用SOS双重检查,没有任何管理的内存泄漏.我也尝试了其他一些证据,但是我认为他们比这更多.
在调查过程中发现的一些有趣的事情:myAction.BeginInvoke调用将使用仪器显示在Profilers上,但myAction.EndInvoke不会显示.