从任务内部的事件中删除委派';s的延续方法
本文关键字:延续 方法 删除 内部 任务 事件 委派 | 更新日期: 2023-09-27 18:27:33
我在父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
的访问器。
我正在尝试删除任务延续方法中的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
?
由于这个原因,为事件处理程序使用匿名方法或lambda是有问题的。您正在添加的委托和试图删除的委托是不同的实例(尽管包含相同的代码)。此问题的解决方案是保存对要添加的委托的引用,或者使用命名方法。有关详细信息,请参阅此问题。
但是,我想问您为什么要首先删除事件处理程序。如果是在特定进程进行时停止处理程序代码的运行,我更喜欢禁用该按钮,然后在处理完成后重新启用它。