Фоновая работа прервать - PullRequest
9 голосов
/ 05 марта 2009

Недавно я попытался использовать backgroundworker вместо «классических» потоков, и я понимаю, что это вызывает, по крайней мере для меня, больше проблем, чем решений. У меня есть фоновый работник, который выполняет синхронное чтение (в данном случае из serialPort) и блокируется около 30 секунд в одной строке кода, тогда отмена отмены не является решением. Я вижу, что если приложение закрывается в этот момент (либо с помощью кросс-кнопки и Application.Exit ()), процесс навсегда удерживает зомби.

Мне нужен способ принудительно прервать или убить поток фонового работника.

Ответы [ 5 ]

5 голосов
/ 07 апреля 2010

Я собрал один, который (я думаю) делает работу. Пожалуйста, дайте мне знать, если я уйду. Вот простой пример того, как это работает.

var backgroundWorker = new BackgroundWorker(){WorkerSupportsCancellation = true};

backgroundWorker.DoWork += (sender, args) =>
         {                 
                 var thisWorker = sender as BackgroundWorker;
                 var _child = new Thread(() =>
                                               {
                                                   //..Do Some Code

                                               });
                 _child .Start();
                 while (_child.IsAlive)
                 {
                     if (thisWorker.CancellationPending)
                     {
                         _child.Abort();
                         args.Cancel = true;
                     }
                     Thread.SpinWait(1);
                 }                 
         };

 backgroundWorker.RunWorkerAsync(parameter);
 //..Do Something...
backgroundWorker.CancelAsync();

Поскольку фоновый работник является частью пула потоков, мы не хотим его прерывать. Но мы можем запустить поток изнутри, который может позволить прервать процесс. Затем backgroundWorker в основном выполняется до тех пор, пока либо дочерний поток не будет завершен, либо мы не дадим ему сигнал убить процесс. Фоновый рабочий поток может затем вернуться в пул чтения. Обычно я заключаю это во вспомогательный класс и пропускаю через метод делегата, который я хочу, чтобы фоновый поток запускал в качестве параметра, и запускал в дочернем потоке.

Пожалуйста, кто-нибудь, дайте мне знать, если я бьюсь головой о стену, но это, кажется, работает нормально .. Но это проблема с потоками, не так ли ... переменные результаты, которые вы можете получить, когда запускаете его в разное время.

3 голосов
/ 06 июля 2009

Процесс не должен превращаться в зомби, поскольку поток BackgroundWorker помечен как "фон" и должен завершиться, когда пользовательский интерфейс закрыт.

2 голосов
/ 05 марта 2009

Я не очень уверен в том, что вы пытаетесь достичь, но, может быть, событие SerialPort.DataReceived является лучшим решением?

Если вы уже освоили использование потоков, я не вижу смысла в использовании BackgroundWorker. Он предназначен для людей, которые в первую очередь не понимают темы.

Кроме того, мне не нравится идея прерывания потока. Это кажется опасным, и многопоточным приложениям больше не нужно рисковать.

2 голосов
/ 05 марта 2009

Я не думаю, что BackgroundWorker поддерживает уничтожение потока. Отмена операции должна быть выполнена в методе, который выполняет работу. В вашем случае я думаю, что лучшим вариантом будет обычная тема.

0 голосов
/ 17 августа 2015

Вы можете попробовать это:

            backgroundworker.Dispose();
            backgroundworker = null;
            GC.Collect(); //this helps cleans up ram
...