使用方法组转换而不是委托很好,EndInvoke
仍然会在您的Action
. 没有什么可做的,因为这是一个“一劳永逸”的电话。
不幸的是,直接无可辩驳地证明调用了 EndInvoke 有点困难,因为Action
它是一个委托,我们不能只在 BCL 中的某个类上添加断点。
此代码将(定期)检查由 返回的 IAsyncResult 的一些私有字段BeginInvoke
,这似乎跟踪是否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
调用将显示在使用仪器的分析器上,但myAction.EndInvoke
不会。