从任务内部的事件中删除委派';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;
}

其中mainFormMdiParent,而stopButton是触发取消/停止进程事件的mainFormToolStripButton的访问器。

我正在尝试删除任务延续方法中的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

从任务内部的事件中删除委派';s的延续方法

由于这个原因,为事件处理程序使用匿名方法或lambda是有问题的。您正在添加的委托和试图删除的委托是不同的实例(尽管包含相同的代码)。此问题的解决方案是保存对要添加的委托的引用,或者使用命名方法。有关详细信息,请参阅此问题。

但是,我想问您为什么要首先删除事件处理程序。如果是在特定进程进行时停止处理程序代码的运行,我更喜欢禁用该按钮,然后在处理完成后重新启用它。