Как полностью "убить" фона рабочего? - программирование
Подтвердить что ты не робот

Как полностью "убить" фона рабочего?

Я пишу приложение Windows, которое неоднократно запускает последовательность цифровых операций ввода-вывода.

Эта последовательность действий начинается, когда пользователь нажимает кнопку "СТАРТ", и это делается фоновым работником в backgroundWorker1_DoWork().

Однако есть случаи, когда я получаю сообщение об ошибке "Этот рабочий стол в данный момент занят.......".

Я думаю о реализации в коде кода следующего кода, используя цикл while, чтобы "убить" рабочего фона перед тем, как начать другую последовательность действий:

if (backgroundWorker1.IsBusy == true)
{

    backgroundWorker1.CancelAsync();
    while (backgroundWorker1.IsBusy == true)
    {
        backgroundWorker1.CancelAsync();
    }

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();

Я думаю, что моя главная проблема заключается в том, что в конце концов будет "убит" backgroundWorker1? Если это произойдет, потребуется много времени, чтобы завершить его?

Будет ли это кодирование вводить меня в бесконечный цикл?

4b9b3361

Ответ 1

Вы можете использовать что-то вроде этого (для получения дополнительной информации об отмене управляемых потоков и об ThreadAbortException см. "" Включение глубин исключения ThreadAbortException с помощью ротора". 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();
}

Ответ 2

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

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

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

Это означает, что если он должен искать сообщение:

  • в нем основной цикл, если он есть.
  • периодически в любых длинных циклах.

Отключение потока с сообщением должно ждать (но не останавливать GUI, конечно).

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

Но обычно проще просто создать приложение, чтобы оставить мастера потоков своей собственной судьбой.

Ответ 3

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

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

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

Ответ 4

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

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

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

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

BackgroundWorker1.CancelAsync()

Надеюсь, это поможет.

Ответ 5

public class abortableBackgroundworker: BackgroundWorker
{
    public bool Kill = false;

    protected override void OnDoWork(DoWorkEventArgs e)
    {


        var _child = new Thread(() =>
        {
            while (!Kill)
            {

            }
            e.Cancel = true;//..Do Some Code

        });
        _child.Start();
        base.OnDoWork(e);

    }



}

вы устанавливаете kill в true, чтобы убить поток и не прерывать проблему:)