В Java все находится в форме класса.
Если вы хотите использовать любой объект, тогда у вас есть две фазы:
Пример:
Object a;
a=new Object();
То же самое для концепции массива
Item i[]=new Item[5];
i[0]=new Item();
Если вы не дают секцию инициализации, тогда возникает NullpointerException
.
Если я понимаю Ваше право требования, Вы могли бы сделать что-то вроде этого (код, не протестированный, но показывает общее представление):
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
}
о, человек, некоторые из них стали смехотворно сложными. все, что необходимо сделать, проверить BackgroundWorker. Свойство CancellationPending в обработчике DoWork. можно проверить его в любое время. как только это находится на рассмотрении, установите e. Отмена = Верный и залог из метода.
//метод здесь частная пустота Worker_DoWork (возражают отправителю, DoWorkEventArgs e) {BackgroundWorker bw = (отправитель как BackgroundWorker);
// do stuff
if(bw.CancellationPending)
{
e.Cancel = True;
return;
}
// do other stuff
}
Рабочий процесс 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
обработчик.
Я не понимаю, почему Вы хотели бы ожидать BackgroundWorker для завершения; это действительно походит на полную противоположность мотивации для класса.
Однако Вы могли запустить каждый метод с вызова рабочему. IsBusy и сделали, чтобы они вышли, если это работает.
Почему Вы не можете только наброситься на BackgroundWorker. Событие RunWorkerCompleted. Это - обратный вызов, который "Произойдет, когда фоновая работа завершилась, была отменена или повысила исключение".
Вы не делаете , ожидают второстепенного рабочего для завершения. Это в значительной степени побеждает цель запустить отдельный поток. Вместо этого необходимо позволить методу закончиться и переместить любой код, который зависит от завершения к различному месту. Вы позволяете рабочему сказать Вам, когда это сделано, и назовите любой остающийся код тогда.
, Если Вы хотите к , ожидают чего-то для завершения, используют различную конструкцию поточной обработки, которая обеспечивает WaitHandle.
Можно зарегистрироваться 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");
}
Почти все Вы смущены вопросом и не понимают, как используется рабочий.
Рассматривают обработчик событий 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();
}
Теперь я мог записать свой код как этот, но я просто не собираюсь. Я не забочусь, я просто нет.
Существует проблема с этот ответ. UI должен продолжить обрабатывать сообщения, в то время как Вы ожидаете, иначе он не перекрасит, который будет проблемой, если Вашему второстепенному рабочему потребуется много времени для ответа на запрос отмены.
А второй дефект - то, что _resetEvent.Set()
никогда не будет называться, если рабочий поток выдаст исключение - отъезд основного потока, ожидающего неограниченно долго - однако, этот дефект мог легко быть зафиксирован с блоком попытки/наконец.
Один способ сделать это должно отобразить модальное диалоговое окно, которое имеет таймер, который неоднократно проверяет, закончил ли второстепенный рабочий работу (или закончил отменять в Вашем случае). Как только второстепенный рабочий закончил, модальное диалоговое управление возвратами к Вашему приложению. Пользователь не может взаимодействовать с UI, пока этого не происходит.
Другой метод (принимающий Вас имеют максимум одного немодального открытого окна) должен установить ActiveForm. Включенный = ложь, затем цикл на Приложении, DoEvents, пока второстепенный рабочий не закончил отменять, после которого можно установить ActiveForm. Включенный = верный снова.
Гм, возможно, я не разбираюсь в Вашем вопросе.
backgroundworker называет событие WorkerCompleted однажды его 'workermethod' (method/function/sub, который обрабатывает backgroundworker.doWork-событие ), закончен, таким образом, нет никакой потребности в проверке, если BW все еще работает. Если Вы хотите остановиться, Ваш рабочий проверяют отмена незаконченное свойство в Вашем 'методе рабочего'.