Как “уничтожить” второстепенного рабочего полностью?

Вы должны установить сущность (имя и категорию) в xcdatamodel.

54
задан lc. 28 April 2009 в 16:43
поделиться

4 ответа

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

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 в основном выполняется до тех пор, пока дочерний поток не будет завершен, или пока мы не дадим ему сигнал убить процесс. Затем фоновый рабочий поток может вернуться в пул чтения. Обычно я заключаю это во вспомогательный класс и передаю метод делегата, который я хочу, чтобы фоновый поток запускался, переданный в качестве параметра, и запускал его в дочернем потоке.

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

0
ответ дан 7 November 2019 в 08:01
поделиться

I'm of the opinion that threads should be responsible for their own resources as much as practicable, including their own lifetime.

It's usually a bad idea to kill threads from outside their scope. Applications that are engineered to pass a message to the thread to shut itself down tend to have far less problems related to multi-threaded behavior.

A thread should monitor for said message, which can be as simple as a boolean set by another thread and read by that monitoring thread, in a timely fashion and shut itself down cleanly as soon as it can.

That means if it should look for the message:

  • in it's main loop, if any.
  • periodically in any long-running loops.

The thread shutting it down with the message should wait (but don't halt the GUI, of course).

Note that there are other possibilities for threaded environments with specific capabilities such as the case where threads can mark themselves cancellable at will, to allow external killing to be safer.

But it's still usually easier to just architect your application to leave a thread master of its own destiny.

18
ответ дан 7 November 2019 в 08:01
поделиться
-

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

Поместите внутри вашего фона работника:

while (backgroundworker1.CancellationPending == false)
{
    //Put your code in here
}

Чтобы убить этот фон фон, вы можете поместить в свою кнопку:

BackgroundWorker1.CancelAsync()

Я надеюсь, что это поможет.

0
ответ дан 7 November 2019 в 08:01
поделиться
-

Вы можете использовать что-то вроде этого (для получения дополнительной информации о прервании управляемых потоков и о ThreadabortException см. « Сантехника Глубины ThreambortException с использованием ротора » Chris Sells):

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

Использование:

backgroundWorker1 = new AbortableBackgroundWorker();
//...
backgroundWorker1.RunWorkerAsync();

if (backgroundWorker1.IsBusy == true)
{
    backgroundWorker1.Abort();
    backgroundWorker1.Dispose();
}
75
ответ дан 7 November 2019 в 08:01
поделиться
Другие вопросы по тегам:

Похожие вопросы: