我在一个父MDI窗体上有一个“停止进程按钮”ToolStripButton。从子窗体中,我使用TPL在后台线程上启动了一个进程,并获得任务返回状态并相应地更改UI。“停止进程按钮”的Click事件是使用delegate处理的,它工作得很好。然而,我似乎不能删除它。请参考下面的代码:
private void buttonRunValid_Click(object sender, EventArgs e)
{
// UI.
mainForm.stopButton.Enabled = true;
// Thread cancellation.
cancelSource = new CancellationTokenSource();
token = cancelSource.Token;
// Start new parallel task and pass uiScheduler.
Task<bool> asyncValidationTask = new Task<bool>(state =>
asyncRunValidationProcess(uiScheduler, token, ref timeSpan),
"Running Validation Process");
asyncValidationTask.Start();
// Callback for cancellation.
asyncValidationTask.ContinueWith(task =>
{
// Do some error checking with task.Status...
// Remove delegate (back on uiThread).
mainForm.stopButton.Click -= delegate
{
UtilsTPL.CancelRunningProcess(ref mainForm, asyncValidationTask, cancelSource);
};
return;
}, TaskScheduler.FromCurrentSynchronizationContext());
// Handle the cancellation.
mainForm.stopButton.Click += delegate
{
UtilsTPL.CancelRunningProcess(ref mainForm, asyncValidationTask, cancelSource);
};
return;
}其中mainForm是MdiParent,stopButton是mainForm的ToolStripButton的访问器,它触发取消/停止进程事件。
我正在尝试删除tasks continuation方法中的delegate,但这不起作用。我还尝试使用反射遍历ToolStripButton包含的所有事件:
FieldInfo fieldInfo =
typeof(Control).GetField("EventClick", BindingFlags.Static | BindingFlags.NonPublic);
object obj = fieldInfo.GetValue(_stripButton);
PropertyInfo propertyInfo =
_stripButton.GetType().GetProperty("Events", BindingFlags.NonPublic | BindingFlags.Instance);
EventHandlerList list = (EventHandlerList)propertyInfo.GetValue(_stripButton, null);
list.RemoveHandler(obj, list[obj]); 这也不起作用。如何删除EventHandler/delegate
发布于 2012-03-13 23:37:31
由于这个原因,使用匿名方法或lambdas作为事件处理程序是有问题的。您添加的委托和您尝试移除的委托是不同的实例(尽管包含相同的代码)。此问题的解决方案是保存对正在添加的委托的引用,或者使用命名方法。See this question获取详细信息。
但是,我想问的是,为什么首先要删除事件处理程序。如果是为了阻止处理程序代码在特定进程运行时运行,我倾向于禁用该按钮,然后在处理完成后重新启用它。
https://stackoverflow.com/questions/9685236
复制相似问题