Удаление делегата из события в методе продолжения задачи - PullRequest
1 голос
/ 13 марта 2012

У меня есть «кнопка остановки процесса» ToolStripButton в родительской форме MDI.Из дочерней формы я запускаю процесс в фоновом потоке, используя TPL, и получаю задачи, возвращающие статус и изменяющий пользовательский интерфейс соответственно.Событие 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?

1 Ответ

3 голосов
/ 13 марта 2012

Использование анонимных методов или лямбд для обработчиков событий проблематично по этой причине. Добавляемый вами делегат и тот, который вы пытаетесь удалить, - это разные экземпляры (несмотря на то, что они содержат идентичный код). Решение этой проблемы состоит либо в сохранении ссылки на делегат, которого вы добавляете, либо в использовании вместо этого именованного метода. Подробнее см. Этот вопрос .

Однако я бы спросил, почему вы в первую очередь удаляете обработчик событий. Если это мешает выполнению кода вашего обработчика во время выполнения определенного процесса, я бы предпочел отключить кнопку, а затем снова включить ее после завершения обработки.

...