Здравствуйте, indusov.net, Вы писали:
IN>При завершении чего?
При завершении приложения.
IN>Он канселит обработку, после чего должен вызваться RunWorkerCompleted.
Cancelling в BackgroundWorker'е — всего лишь взведение соответствующего флажка. Исполнение DoWork никто не прерывает. Если хочется реального cancelling'а, то его нужно делать ручками в DoWork. Ничего подобного в коде топикстартера не наблюдается — его DoWork будет молотить до победы.
Здравствуйте, drol, Вы писали:
D>Здравствуйте, indusov.net, Вы писали:
IN>>При завершении чего?
D>При завершении приложения.
IN>>Он канселит обработку, после чего должен вызваться RunWorkerCompleted.
D>Cancelling в BackgroundWorker'е — всего лишь взведение соответствующего флажка. Исполнение DoWork никто не прерывает. Если хочется реального cancelling'а, то его нужно делать ручками в DoWork. Ничего подобного в коде топикстартера не наблюдается — его DoWork будет молотить до победы.
Да, 15 секунд отладки кода топикстартера показали твою правоту
После CancelAsync мы успешно продолжаем приходить в DoWork.
http://www.developerdotstar.com/community/node/671
Здравствуйте, drol, Вы писали:
D>Cancelling в BackgroundWorker'е — всего лишь взведение соответствующего флажка. Исполнение DoWork никто не прерывает. Если хочется реального cancelling'а, то его нужно делать ручками в DoWork. Ничего подобного в коде топикстартера не наблюдается — его DoWork будет молотить до победы.
Да, 15 секунд отладки кода топикстартера показали твою правоту
После CancelAsync мы успешно продолжаем приходить в DoWork.
http://www.developerdotstar.com/community/node/671
В общем, ответ нашелся:
static void bw_DoWork(object sender, DoWorkEventArgs e)
{
for (int i = 0; i < 10000; i++)
{
Thread.Sleep(1000);
Console.WriteLine(i);
if (bw.CancellationPending )
{
e.Result = "done";
return ;
}
}
}
И все нормально прерывается!
Вот только как бы сделать уведомление о прерывании треда, если тред исполняет одну долгоиграющую функцию, к-рая не может ничего знать о CancellationPending и пр. деталях ее вызова? Не важно , как это сделать — без BackgroundWorker или с ним.
Здравствуйте, senglory, Вы писали:
S>Вот только как бы сделать уведомление о прерывании треда, если тред исполняет одну долгоиграющую функцию, к-рая не может ничего знать о CancellationPending и пр. деталях ее вызова? Не важно , как это сделать — без BackgroundWorker или с ним.
Еще раз повторюсь. Почитай
здесь. Здесь же именно твой случай и расписывается.
public class AbortableBackgroundWorker : BackgroundWorker
{
private Thread workerThread;
protected override void OnDoWork(DoWorkEventArgs e)
{
workerThread = Thread.CurrentThread;
try
{
base.OnDoWork(e);
}
catch (ThreadAbortException)
{
e.Cancel = true; //We must set Cancel property to true!
Thread.ResetAbort(); //Prevents ThreadAbortException propagation
}
}
public void Abort()
{
if (workerThread != null)
{
workerThread.Abort();
workerThread = null;
}
}
}
Основная работа делается в переопределенном методе OnDoWork, который уже вызывается в потоке пула потоков (т.к. реализация класса BackgroundWorker основана на пуле потоков). В этом методе запоминается поток, выполняющий текущую операцию, и в методе Abort вызывается метод Abort этого потока.
Прерывание потока путем вызова метода Thread.Abort имеет некоторые особенности, которые нужно учитывать, как при реализации класса AbortableBackgroundWorker, так и его клиентов. Исключение ThreadAbortException является особенным типом исключения, которое трактуется CLR особым образом. Основная особенность в том, что после выполнения блоков catch и finally никакой код выполняться не будет, а учитывая, что прерываемый поток является потоком из пула потоков, то ни к чему хорошему это не приведет. Именно поэтому в обработчике исключения ThreadAbortException метода OnDoWork вызывается метод Thread.ResetAbort, который предотвращает распространение исключения ThreadAbortException и выполнения потока продолжается, но уже не с того места, где он выполнялся (в середине длительной операции), а так, как будто асинхронная операция успешно завершилась.
На клиентов класса AbortableBackgroundWorker, также налагаются некоторые ограничения, связанной с прерыванием рабочего потока. Во-первых, если обработчик события DoWork содержит обработку исключения, то там должно быть дополнительный блок catch для исключения ThreadAbortException, который обрабатывать на этом уровне не нужно. Во-вторых, исключение ThreadAbortException относится к асинхронным исключениями, которые могут возникнуть в любой точке управляемого кода, что может привести к непредвиденным последствиям и рассогласованному состоянию приложения. Например, если будет прерван поток, выполняющий статический конструктор некоторого класса, то последующее обращение к этому классу также будет приводить к генерации исключения TypeLoadException. В-третьих, CLR не всегда сможет прервать выполнение потока. Так, например, прерывание потока будет невозможно, если поток выполняет неуправляемый код или блоки catch/finally управляемого кода.