Как ожидать BackgroundWorker для отмены?

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

119
задан A876 28 April 2017 в 22:33
поделиться

10 ответов

Если я понимаю Ваше право требования, Вы могли бы сделать что-то вроде этого (код, не протестированный, но показывает общее представление):

private BackgroundWorker worker = new BackgroundWorker();
private AutoResetEvent _resetEvent = new AutoResetEvent(false);

public Form1()
{
    InitializeComponent();

    worker.DoWork += worker_DoWork;
}

public void Cancel()
{
    worker.CancelAsync();
    _resetEvent.WaitOne(); // will block until _resetEvent.Set() call made
}

void worker_DoWork(object sender, DoWorkEventArgs e)
{
    while(!e.Cancel)
    {
        // do something
    }

    _resetEvent.Set(); // signal that worker is done
}
123
ответ дан Fredrik Kalseth 24 November 2019 в 01:51
поделиться

о, человек, некоторые из них стали смехотворно сложными. все, что необходимо сделать, проверить BackgroundWorker. Свойство CancellationPending в обработчике DoWork. можно проверить его в любое время. как только это находится на рассмотрении, установите e. Отмена = Верный и залог из метода.

//метод здесь частная пустота Worker_DoWork (возражают отправителю, DoWorkEventArgs e) {BackgroundWorker bw = (отправитель как BackgroundWorker);

// do stuff

if(bw.CancellationPending)
{
    e.Cancel = True;
    return;
}

// do other stuff

}

-2
ответ дан 24 November 2019 в 01:51
поделиться

Рабочий процесс BackgroundWorker объект в основном требует, чтобы Вы обработали RunWorkerCompleted событие и для нормального выполнения и для пользовательских вариантов использования отмены. Это то, почему свойство RunWorkerCompletedEventArgs. Отмененный существует. В основном выполнение этого правильно требует, чтобы Вы полагали, что Ваш метод Отмены асинхронный метод сам по себе.

Вот пример:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.ComponentModel;

namespace WindowsFormsApplication1
{
    public class AsyncForm : Form
    {
        private Button _startButton;
        private Label _statusLabel;
        private Button _stopButton;
        private MyWorker _worker;

        public AsyncForm()
        {
            var layoutPanel = new TableLayoutPanel();
            layoutPanel.Dock = DockStyle.Fill;
            layoutPanel.ColumnStyles.Add(new ColumnStyle());
            layoutPanel.ColumnStyles.Add(new ColumnStyle());
            layoutPanel.RowStyles.Add(new RowStyle(SizeType.AutoSize));
            layoutPanel.RowStyles.Add(new RowStyle(SizeType.Percent, 100));

            _statusLabel = new Label();
            _statusLabel.Text = "Idle.";
            layoutPanel.Controls.Add(_statusLabel, 0, 0);

            _startButton = new Button();
            _startButton.Text = "Start";
            _startButton.Click += HandleStartButton;
            layoutPanel.Controls.Add(_startButton, 0, 1);

            _stopButton = new Button();
            _stopButton.Enabled = false;
            _stopButton.Text = "Stop";
            _stopButton.Click += HandleStopButton;
            layoutPanel.Controls.Add(_stopButton, 1, 1);

            this.Controls.Add(layoutPanel);
        }

        private void HandleStartButton(object sender, EventArgs e)
        {
            _stopButton.Enabled = true;
            _startButton.Enabled = false;

            _worker = new MyWorker() { WorkerSupportsCancellation = true };
            _worker.RunWorkerCompleted += HandleWorkerCompleted;
            _worker.RunWorkerAsync();

            _statusLabel.Text = "Running...";
        }

        private void HandleStopButton(object sender, EventArgs e)
        {
            _worker.CancelAsync();
            _statusLabel.Text = "Cancelling...";
        }

        private void HandleWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled)
            {
                _statusLabel.Text = "Cancelled!";
            }
            else
            {
                _statusLabel.Text = "Completed.";
            }

            _stopButton.Enabled = false;
            _startButton.Enabled = true;
        }

    }

    public class MyWorker : BackgroundWorker
    {
        protected override void OnDoWork(DoWorkEventArgs e)
        {
            base.OnDoWork(e);

            for (int i = 0; i < 10; i++)
            {
                System.Threading.Thread.Sleep(500);

                if (this.CancellationPending)
                {
                    e.Cancel = true;
                    e.Result = false;
                    return;
                }
            }

            e.Result = true;
        }
    }
}

, Если бы Вы действительно действительно не хотите, чтобы Ваш метод вышел, я предложил бы поместить флаг как AutoResetEvent на полученном BackgroundWorker, затем переопределил бы OnRunWorkerCompleted для установки флага. Это все еще довольно топорно хотя; я рекомендовал бы рассматривать событие отмены как асинхронный метод и сделал бы то, что оно в настоящее время делает в RunWorkerCompleted обработчик.

0
ответ дан OwenP 24 November 2019 в 01:51
поделиться

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

Однако Вы могли запустить каждый метод с вызова рабочему. IsBusy и сделали, чтобы они вышли, если это работает.

1
ответ дан Austin Salonen 24 November 2019 в 01:51
поделиться

Почему Вы не можете только наброситься на BackgroundWorker. Событие RunWorkerCompleted. Это - обратный вызов, который "Произойдет, когда фоновая работа завершилась, была отменена или повысила исключение".

3
ответ дан Rick Minerich 24 November 2019 в 01:51
поделиться

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

, Если Вы хотите к , ожидают чего-то для завершения, используют различную конструкцию поточной обработки, которая обеспечивает WaitHandle.

4
ответ дан Joel Coehoorn 24 November 2019 в 01:51
поделиться

Можно зарегистрироваться RunWorkerCompletedEventArgs в RunWorkerCompletedEventHandler для наблюдения, каково состояние было. Успех, отмененный или ошибка.

private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
    if(e.Cancelled)
    {
        Console.WriteLine("The worker was cancelled.");
    }
}

Обновление : Чтобы видеть, назвал ли Ваш рабочий.CancelAsync () при помощи этого:

if (_worker.CancellationPending)
{
    Console.WriteLine("Cancellation is pending, no need to call CancelAsync again");
}
4
ответ дан Seb Nilsson 24 November 2019 в 01:51
поделиться

Почти все Вы смущены вопросом и не понимают, как используется рабочий.

Рассматривают обработчик событий RunWorkerComplete:

private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (!e.Cancelled)
    {
        rocketOnPad = false;
        label1.Text = "Rocket launch complete.";
    }
    else
    {
        rocketOnPad = true;
        label1.Text = "Rocket launch aborted.";
    }
    worker = null;
}

И все хорошо.

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

private void BlowUpRocket()
{
    if (worker != null)
    {
        worker.CancelAsync();
        WaitForWorkerToFinish(worker);
        worker = null;
    }

    StartClaxon();
    SelfDestruct();
}

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

private void OpenAccessGates()
{
    if (worker != null)
    {
        worker.CancelAsync();
        WaitForWorkerToFinish(worker);
        worker = null;
    }

    if (!rocketOnPad)
        DisengageAllGateLatches();
}

И наконец, мы должны откачать топливо с ракеты, но это не позволяется во время обратного отсчета:

private void DrainRocket()
{
    if (worker != null)
    {
        worker.CancelAsync();
        WaitForWorkerToFinish(worker);
        worker = null;
    }

    if (rocketOnPad)
        OpenFuelValves();
}

Без способности ожидать рабочего для отмены мы должны переместить все три метода в RunWorkerCompletedEvent:

private void OnRunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    if (!e.Cancelled)
    {
        rocketOnPad = false;
        label1.Text = "Rocket launch complete.";
    }
    else
    {
        rocketOnPad = true;
        label1.Text = "Rocket launch aborted.";
    }
    worker = null;

    if (delayedBlowUpRocket)
        BlowUpRocket();
    else if (delayedOpenAccessGates)
        OpenAccessGates();
    else if (delayedDrainRocket)
        DrainRocket();
}

private void BlowUpRocket()
{
    if (worker != null)
    {
        delayedBlowUpRocket = true;
        worker.CancelAsync();
        return;
    }

    StartClaxon();
    SelfDestruct();
}

private void OpenAccessGates()
{
    if (worker != null)
    {
        delayedOpenAccessGates = true;
        worker.CancelAsync();
        return;
    }

    if (!rocketOnPad)
        DisengageAllGateLatches();
}

private void DrainRocket()
{
    if (worker != null)
    {
        delayedDrainRocket = true;
        worker.CancelAsync();
        return;
    }

    if (rocketOnPad)
        OpenFuelValves();
}

Теперь я мог записать свой код как этот, но я просто не собираюсь. Я не забочусь, я просто нет.

10
ответ дан A876 24 November 2019 в 01:51
поделиться

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

А второй дефект - то, что _resetEvent.Set() никогда не будет называться, если рабочий поток выдаст исключение - отъезд основного потока, ожидающего неограниченно долго - однако, этот дефект мог легко быть зафиксирован с блоком попытки/наконец.

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

Другой метод (принимающий Вас имеют максимум одного немодального открытого окна) должен установить ActiveForm. Включенный = ложь, затем цикл на Приложении, DoEvents, пока второстепенный рабочий не закончил отменять, после которого можно установить ActiveForm. Включенный = верный снова.

14
ответ дан Community 24 November 2019 в 01:51
поделиться

Гм, возможно, я не разбираюсь в Вашем вопросе.

backgroundworker называет событие WorkerCompleted однажды его 'workermethod' (method/function/sub, который обрабатывает backgroundworker.doWork-событие ), закончен, таким образом, нет никакой потребности в проверке, если BW все еще работает. Если Вы хотите остановиться, Ваш рабочий проверяют отмена незаконченное свойство в Вашем 'методе рабочего'.

0
ответ дан Stephan 24 November 2019 в 01:51
поделиться
Другие вопросы по тегам:

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