Отмена задачи ThreadPool .QueueUserWorkItem - PullRequest
2 голосов
/ 11 октября 2011

Мне нужно отменить фоновую задачу, запущенную с помощью ThreadPool.QueueUserWorkItem (...). Я знаю, что у BackgroundWorker есть конструкции, специально предназначенные для такого рода вещей, но я считаю, что в этом случае это излишне, поскольку не задействован пользовательский интерфейс. Под отменой я просто подразумеваю принудительное завершение метода обратного вызова.

Каковы ловушки добавления чего-то вроде следующего в мой класс?

// Cancellation Property.
private bool _canceled;
public bool CancelTask
{
    get { return _canceled; }
    set { _canceled = value; }
}

public void DoSomeTask()
{
    int iterations = 50;
    ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadPoolCallback), iterations);
}

private void ThreadPoolCallback(object state)
{
    if (_canceled)
        return; // don't even start.

    int iterations = (int)state;
    for (int i = 0; !_canceled && i < iterations; i++)
    {
        //
        // do work ...
        //

        // This allows you to cancel in the middle of an iteration...
        if (_canceled)
            break;
    }
}

Есть ли лучший способ?

1 Ответ

3 голосов
/ 11 октября 2011

Я бы использовал метод CancelTask ​​(), а не свойство. Дело в том, что вызывающие абоненты должны иметь возможность отменить задачу, но никто не должен иметь возможность отменить задачу.

Тогда вы должны быть уверены, что чтение и запись _cancelled имеют соответствующие барьеры памяти, иначе один поток может не заметить изменения, сделанные другим потоком. Для этого я бы использовал Thread.VolatileWrite (внутри CancelTask) и Thread.VolatileRead (внутри цикла)

...