Re[5]: Почему не срабатывает RunWorkerCompleted?
От: drol  
Дата: 05.08.09 06:31
Оценка: 1 (1) +1
Здравствуйте, indusov.net, Вы писали:

IN>При завершении чего?


При завершении приложения.

IN>Он канселит обработку, после чего должен вызваться RunWorkerCompleted.


Cancelling в BackgroundWorker'е — всего лишь взведение соответствующего флажка. Исполнение DoWork никто не прерывает. Если хочется реального cancelling'а, то его нужно делать ручками в DoWork. Ничего подобного в коде топикстартера не наблюдается — его DoWork будет молотить до победы.
Re[7]: Почему не срабатывает RunWorkerCompleted?
От: indusov.net Россия indusov.net
Дата: 05.08.09 10:10
Оценка:
Здравствуйте, drol, Вы писали:

D>Вы просто не понимаете как работает механизма.

Чукча не читатель, чукча писатель.
Re[6]: Почему не срабатывает RunWorkerCompleted?
От: Аноним  
Дата: 05.08.09 10:21
Оценка:
Здравствуйте, 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
Re[6]: Почему не срабатывает RunWorkerCompleted?
От: indusov.net Россия indusov.net
Дата: 05.08.09 10:25
Оценка:
Здравствуйте, drol, Вы писали:

D>Cancelling в BackgroundWorker'е — всего лишь взведение соответствующего флажка. Исполнение DoWork никто не прерывает. Если хочется реального cancelling'а, то его нужно делать ручками в DoWork. Ничего подобного в коде топикстартера не наблюдается — его DoWork будет молотить до победы.


Да, 15 секунд отладки кода топикстартера показали твою правоту
После CancelAsync мы успешно продолжаем приходить в DoWork.


http://www.developerdotstar.com/community/node/671
Re: Почему не срабатывает RunWorkerCompleted?
От: senglory  
Дата: 05.08.09 15:15
Оценка:
В общем, ответ нашелся:


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 ;
                }
            }
        }



И все нормально прерывается!
Re[2]: Почему не срабатывает RunWorkerCompleted?
От: senglory  
Дата: 05.08.09 18:40
Оценка:
Вот только как бы сделать уведомление о прерывании треда, если тред исполняет одну долгоиграющую функцию, к-рая не может ничего знать о CancellationPending и пр. деталях ее вызова? Не важно , как это сделать — без BackgroundWorker или с ним.
Re[3]: Почему не срабатывает RunWorkerCompleted?
От: SergeyT. США http://sergeyteplyakov.blogspot.com/
Дата: 06.08.09 07:18
Оценка:
Здравствуйте, 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 управляемого кода.

Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.