문제

고려 방법 개체는 물건은 당신을 위해:

public class DoesStuff
{
    BackgroundWorker _worker = new BackgroundWorker();

    ...

    public void CancelDoingStuff()
    {
        _worker.CancelAsync();

        //todo: Figure out a way to wait for BackgroundWorker to be cancelled.
    }
}

할 수 있습니다 어떻게 해야 하나를 기다릴 BackgroundWorker 할 수 있습니까?


과거에 사람들이 노력했:

while (_worker.IsBusy)
{
    Sleep(100);
}

이 교착 상태, 기 때문에, IsBusy 지워지지 않을 때까지 후 RunWorkerCompleted 이벤트 처리,그리고 이벤트를 얻을 수 없을 처리할 때까지 신청가 유휴 상태입니다.응용 프로그램이 없는 유휴 상태가 될 때까지 노동자입니다.(또한,그것이 바쁜 반복-역겨운.)

다른 사람을 추가 제안 kludging 으로 그것:

while (_worker.IsBusy)
{
    Application.DoEvents();
}

문제는 즉 Application.DoEvents() 원인 메시지 현재 큐에 처리하는 원인 re-entrancy 제(.NET 지 않은 다시 참가자에게).

내가 사용하는 희망 어떤 솔루션을 포함하는 이벤트가 동기화체 코드 한 이벤트는 근로자의 RunWorkerCompleted 이벤트 처리합니다.다음과 같습니다.

Event _workerDoneEvent = new WaitHandle();

public void CancelDoingStuff()
{
    _worker.CancelAsync();
    _workerDoneEvent.WaitOne();
}

private void RunWorkerCompletedEventHandler(sender object, RunWorkerCompletedEventArgs e)
{
    _workerDoneEvent.SetEvent();
}

그러나 내가 다시는 교착 상태:이벤트 핸들러를 실행할 수 없을 때까지 신청가 유휴 상태이며,응용 프로그램을 가지 않을 것이기 때문에 유휴 상태 기다리고 있는 이벤트입니다.

그래서 어떻게 할 수 있는 기다릴 BackgroundWorker 마무리 하는가?


업데이트 사람들이 혼동해서 이 질문입니다.그들은 생각하는 것 내가 사용하는 것 BackgroundWorker 로:

BackgroundWorker worker = new BackgroundWorker();
worker.DoWork += MyWork;
worker.RunWorkerAsync();
WaitForWorkerToFinish(worker);

그것은 내가 무엇을 하고,그 게 묻고 있는 것이 여기에.그런 경우라면,없을 것이라는 점에서 배경을 사용하여 노동자입니다.

도움이 되었습니까?

해결책

내가 이해하는 경우 귀하의 요구 사항 오른쪽,당신이 뭔가를 할 수 있습니다(코드를 테스트하지만 보여 줍니다 일반적인 아이디어):

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
}

다른 팁

에 문제가 있으로 응답입니다.UI 계속하는 데 필요한 메시지를 처리하는 동안 기다리고 있는,그렇지 않으면 그것은 다시 그려지지 않는 것이 문제가 될 경우 작업자의 배경이 오래 걸리는 시간에 응답 취소를 요청합니다.

두 번째는 _resetEvent.Set() 을 것이라고 경우는 worker 쓰레드가 발생하는 예외를 떠나는 메인 스레드 기다리고 무기한-그러나 이러한 결함을 쉽게 해결 될 수 있 try/마지막으로 차단합니다.

방법 중 하나 이렇게하기 위해 최선을 다할 것입달 대화가 있는 타이머는 반복적으로 확인하면 백그라운드 작업자가 완료된 작업(또는 완료 취소하신 경우).면 백그라운드 작업자가 완료되면 모달을 대화를 반환하 제어 응용 프로그램입니다.사용자와 상호 작용할 수 없습 UI 까지 이 발생합니다.

다른 방법(가정이 있는 최대의 하나는 모달리스 창을 열)설정하는 것이 ActiveForm.사용 가능=false,다 루는 응용 프로그램,DoEvents 까지 배경을 작업자가 완료되면 제거 한 후,당신은 설정할 수 있습니다 ActiveForm.Enabled=true 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();
}

그리고 마지막으로,우리는 필요하 de-연료켓,하지만 그 중에 허용되지 않습트:

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

지금 내가 쓸 수 있는 내 코드는,하지만 난 그냥하지 않을 거야.내가 관심이 없어 난 그냥하지 않습니다.

을 확인할 수 있습으로 RunWorkerCompletedEventArgsRunWorkerCompletedEventHandler 무엇을 보는 상태였다.성공,취소 또는 오류가 있습니다.

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

당신 기다리는 작업자의 배경을 완료합니다.꽤 많은 패배의 목적을 실행하는 별도의 스레드가 있습니다.대신에,당신은 당신의 방법은 완료,이동하는 모든 코드에 따라 완료하는 다른 장소입니다.당신이 작업자에게 말을 때 수행하고 부르지는 않습니다.

하려는 경우 무언가를 위해 완전한 사용이 다른 스레딩 구성을 제공하는 WaitHandle.

할 수 있습니다.로 넥타이 BackgroundWorker.RunWorkerCompleted 이벤트입니다.그것은 콜백하는 것이"발생할 경우 배경 작업이 완료된,취소,또는 발생하는 예외는 아니다."

난 이해하지 못하는 원을 기다리는 BackgroundWorker 색그것은 정말처럼 보인다 정확히 반대의 동기 부여한다.

그러나,당신은 시작할 수있는 모든 방법으로 통화를하는 노동자입니다.IsBusy 고 있는 그들을 종료하면 그것은 실행됩니다.

그냥 말하고 싶은 나왔기 때문에 여기에 내가 필요한 배경을 작업자를 기다리는 동안 나는 실행하는 비동기 프로세스 동안,루프에서 내가 해결 되었는 방법보다 쉽게 이 모든 다른 물건^^

foreach(DataRow rw in dt.Rows)
{
     //loop code
     while(!backgroundWorker1.IsBusy)
     {
         backgroundWorker1.RunWorkerAsync();
     }
}

다만 생각했던 공유기 때문에 이것은 결국을 찾고 있는 동안에 대한 솔루션입니다.또한,이번이 처음에 게시 stack overflow 그렇다면 그 나쁜 또는 아무것도 나는 사랑을 비평가!:)

Hm 어쩌면 나는 못하고 오른쪽으로 당신의 질문에.

Backgroundworker 호출 WorkerCompleted 이벤트는 한 번 자신의'workermethod'(메서드/수/서브를 처리하는 backgroundworker.면서 이벤트 이)완료 할 필요가 없도록 확인하는 경우 BW 계속 실행됩니다.을 중지하려는 경우 담당자 확인 취소 보류 중인 시설 내부의'작업자의 방식이 가능합니다.

의 워크플로 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, 다음 override OnRunWorkerCompleted 하는 플래그를 설정합니다.그것은 여전히 종류의 의견을 더욱 쉽게 확인하지만;내가 권하고 싶을 치료 취소하는 이벤트 같은 비동기 방법 및 무엇이든 할 그것은 현재 하에서 RunWorkerCompleted 처리기입니다.

저는 조금 늦게 자기(약 4 년)그러나 어떤 설정에 대해 비동기식 스레드를 처리할 수 있는 바쁜 반복 없이 잠금 UI,다음 콜백에서는 스레드가 될 수 있는지 확인 BackgroundWorker 완료 취소?

무언가 이것을 좋아한다:

class Test : Form
{
    private BackgroundWorker MyWorker = new BackgroundWorker();

    public Test() {
        MyWorker.DoWork += new DoWorkEventHandler(MyWorker_DoWork);
    }

    void MyWorker_DoWork(object sender, DoWorkEventArgs e) {
        for (int i = 0; i < 100; i++) {
            //Do stuff here
            System.Threading.Thread.Sleep((new Random()).Next(0, 1000));  //WARN: Artificial latency here
            if (MyWorker.CancellationPending) { return; } //Bail out if MyWorker is cancelled
        }
    }

    public void CancelWorker() {
        if (MyWorker != null && MyWorker.IsBusy) {
            MyWorker.CancelAsync();
            System.Threading.ThreadStart WaitThread = new System.Threading.ThreadStart(delegate() {
                while (MyWorker.IsBusy) {
                    System.Threading.Thread.Sleep(100);
                }
            });
            WaitThread.BeginInvoke(a => {
                Invoke((MethodInvoker)delegate() { //Invoke your StuffAfterCancellation call back onto the UI thread
                    StuffAfterCancellation();
                });
            }, null);
        } else {
            StuffAfterCancellation();
        }
    }

    private void StuffAfterCancellation() {
        //Things to do after MyWorker is cancelled
    }
}

본질이 무엇은 화재 다른 스레드가 백그라운드에서 실행하는 그냥 대기에서 그것은 바쁜 반복하십시오 MyWorker 가 완료되었습니다.면 MyWorker 가 완료되면을 취소하는 스레드가 종료됩니다 우리가 사용할 수 있습니다 그것은 AsyncCallback 실행하는 어떤 방법을 우리에게 필요를 따라 성공적으 취소 수-그것은 일하는 것과 같은 의사의 이벤트입니다.이 때문에 별도의 UI 스레드에서 그것은 잠되지 않 UI 를 기다리는 동안 MyWorker 을 취소 마감.당신의 의도 정말 잠금 및 대기 취소 다음이 쓸모없는,하지만 당신은 그냥 기다려야 할 수 있도록 다른 프로세스를 시작한 다음이 작동합니다.

내가 이것을 알고 정말 늦(5 년제)하지만 당신이 찾고있는 무엇이 스레드를 사용하고 SynchronizationContext.당신이해야 할 것을 원수 UI 를 다시 호출하는 UI 스레드"손으로"보다는 오히려 하자 Framework 그것을 자동으로 마술.

이것은 당신이 스레드를 사용하는 기다릴 수 있는 경우에 요구됩니다.

Imports System.Net
Imports System.IO
Imports System.Text

Public Class Form1
   Dim f As New Windows.Forms.Form
  Private Sub Button1_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles Button1.Click
   BackgroundWorker1.WorkerReportsProgress = True
    BackgroundWorker1.RunWorkerAsync()
    Dim l As New Label
    l.Text = "Please Wait"
    f.Controls.Add(l)
    l.Dock = DockStyle.Fill
    f.StartPosition = FormStartPosition.CenterScreen
    f.FormBorderStyle = Windows.Forms.FormBorderStyle.None
    While BackgroundWorker1.IsBusy
        f.ShowDialog()
    End While
End Sub




Private Sub BackgroundWorker1_DoWork(ByVal sender As Object, ByVal e As System.ComponentModel.DoWorkEventArgs) Handles BackgroundWorker1.DoWork

    Dim i As Integer
    For i = 1 To 5
        Threading.Thread.Sleep(5000)
        BackgroundWorker1.ReportProgress((i / 5) * 100)
    Next
End Sub

Private Sub BackgroundWorker1_ProgressChanged(ByVal sender As Object, ByVal e As System.ComponentModel.ProgressChangedEventArgs) Handles BackgroundWorker1.ProgressChanged
    Me.Text = e.ProgressPercentage

End Sub

 Private Sub BackgroundWorker1_RunWorkerCompleted(ByVal sender As Object, ByVal e As System.ComponentModel.RunWorkerCompletedEventArgs) Handles BackgroundWorker1.RunWorkerCompleted

    f.Close()

End Sub

End Class

프레드릭 Kalseth 의 이 문제에 대한 해결책은 지금까지 발견 했습니다.다른 솔루션을 사용하여 Application.DoEvent() 을 일으킬 수 있는 문제 또는 단순히 일하지 않는다.나 자신의 캐스팅 솔루션으로 재사용할 수 있는 클래스입니다.이 BackgroundWorker 지 않은 밀봉하는,우리는 파생 수 있습니다 우리의 클래스에서는것:

public class BackgroundWorkerEx : BackgroundWorker
{
    private AutoResetEvent _resetEvent = new AutoResetEvent(false);
    private bool _resetting, _started;
    private object _lockObject = new object();

    public void CancelSync()
    {
        bool doReset = false;
        lock (_lockObject) {
            if (_started && !_resetting) {
                _resetting = true;
                doReset = true;
            }
        }
        if (doReset) {
            CancelAsync();
            _resetEvent.WaitOne();
            lock (_lockObject) {
                _started = false;
                _resetting = false;
            }
        }
    }

    protected override void OnDoWork(DoWorkEventArgs e)
    {
        lock (_lockObject) {
            _resetting = false;
            _started = true;
            _resetEvent.Reset();
        }
        try {
            base.OnDoWork(e);
        } finally {
            _resetEvent.Set();
        }
    }
}

플래그와 함께하고 적절한 잠금,우리는 확인 _resetEvent.WaitOne() 정말만 호출하는 경우 몇 가지 작업이 시작되었습,그렇지 않으면 _resetEvent.Set(); 되지 않을 수도 있습니다.

Try-마지막으로는 것을 보장 _resetEvent.Set(); 호출될 경우에도 예외가 발생한 우리나면서-handler.그렇지 않으면 응용 프로그램을 수 있는 동결 영원히 호출할 때 CancelSync!

우리는 이를 다음과 같이 사용:

BackgroundWorkerEx _worker;

void StartWork()
{
    StopWork();
    _worker = new BackgroundWorkerEx { 
        WorkerSupportsCancellation = true,
        WorkerReportsProgress = true
    };
    _worker.DoWork += Worker_DoWork;
    _worker.ProgressChanged += Worker_ProgressChanged;
}

void StopWork()
{
    if (_worker != null) {
        _worker.CancelSync(); // Use our new method.
    }
}

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 20; i++) {
        if (worker.CancellationPending) {
            e.Cancel = true;
            break;
        } else {
            // Simulate a time consuming operation.
            System.Threading.Thread.Sleep(500);
            worker.ReportProgress(5 * i);
        }
    }
}

private void Worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
    progressLabel.Text = e.ProgressPercentage.ToString() + "%";
}

할 수도 있습니다 추가 처리기 RunWorkerCompleted 이벤트와 같이 여기:
     BackgroundWorker 클래스 (Microsoft 설명서).

닫 양식을 닫고 내 logfile.내 백그라운드 작업자를 쓰는 로그파일,그래서 나는 할 수 없습 MainWin_FormClosing() 끝까지 내 백그라운드 작업자가 종료됩니다.면 기다리지 않는 내 백그라운드 작업자를 종료하,예외가 일어난다.

이것이 왜 그렇게 어려울까요?

간단한 Thread.Sleep(1500) 작동,하지만 지연이 종료(너무 긴 경우),또는 원인이 예외(너무 짧은 경우).

을 종료 후 오른쪽 배경을 작업자가 종료만 사용하는 변수입니다.이것은 나를 위해 일하고:

private volatile bool bwRunning = false;

...

private void MainWin_FormClosing(Object sender, FormClosingEventArgs e)
{
    ... // Clean house as-needed.

    bwInstance.CancelAsync();  // Flag background worker to stop.
    while (bwRunning)
        Thread.Sleep(100);  // Wait for background worker to stop.
}  // (The form really gets closed now.)

...

private void bwBody(object sender, DoWorkEventArgs e)
{
    bwRunning = true;

    BackgroundWorker bw = sender as BackgroundWorker;

    ... // Set up (open logfile, etc.)

    for (; ; )  // infinite loop
    {
        ...
        if (bw.CancellationPending) break;
        ...
    } 

    ... // Tear down (close logfile, etc.)

    bwRunning = false;
}  // (bwInstance dies now.)

할 수 있습 돼지의 RunWorkerCompleted 이벤트입니다.는 경우에도 당신은 이미 추가되는 이벤트에 대한 처리기 _worker,당신은 다른 추가할 수 있는 것이 실행에는 순서가 추가되었습니다.

public class DoesStuff
{
    BackgroundWorker _worker = new BackgroundWorker();

    ...

    public void CancelDoingStuff()
    {
        _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) => 
        {
            // do whatever you want to do when the cancel completes in here!
        });
        _worker.CancelAsync();
    }
}

이것이 유용할 수 있는 경우에 당신은 여러 가지 이유 취소 발생할 수 있습니다,만들의 논리 단일 RunWorkerCompleted 처리기 더 복잡도 있습니다.예를 들어,을 취소하는 경우 사용자가 양식을 닫:

void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
    if (_worker != null)
    {
        _worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler((sender, e) => this.Close());
        _worker.CancelAsync();
        e.Cancel = true;
    }
}

내가 사용하는 async 방법 await 를 기다리는 작업자를 마무리 작업:

    public async Task StopAsync()
    {
        _worker.CancelAsync();

        while (_isBusy)
            await Task.Delay(1);
    }

고서 DoWork 방법:

    public async Task DoWork()
    {
        _isBusy = true;
        while (!_worker.CancellationPending)
        {
            // Do something.
        }
        _isBusy = false;
    }

수도 있습니다 캡슐화 while 루프 DoWorktry ... catch_isBusyfalse 에 예외는 아니다.거나,단순히 체크 _worker.IsBusyStopAsync 는 동안 반복입니다.

여기에는 예의 전체 구현:

class MyBackgroundWorker
{
    private BackgroundWorker _worker;
    private bool _isBusy;

    public void Start()
    {
        if (_isBusy)
            throw new InvalidOperationException("Cannot start as a background worker is already running.");

        InitialiseWorker();
        _worker.RunWorkerAsync();
    }

    public async Task StopAsync()
    {
        if (!_isBusy)
            throw new InvalidOperationException("Cannot stop as there is no running background worker.");

        _worker.CancelAsync();

        while (_isBusy)
            await Task.Delay(1);

        _worker.Dispose();
    }

    private void InitialiseWorker()
    {
        _worker = new BackgroundWorker
        {
            WorkerSupportsCancellation = true
        };
        _worker.DoWork += WorkerDoWork;
    }

    private void WorkerDoWork(object sender, DoWorkEventArgs e)
    {
        _isBusy = true;
        try
        {
            while (!_worker.CancellationPending)
            {
                // Do something.
            }
        }
        catch
        {
            _isBusy = false;
            throw;
        }

        _isBusy = false;
    }
}

을 중지하는 노동자 및 기다리는 그것을 끝까지 진행됩:

await myBackgroundWorker.StopAsync();

문제로 이 방법:

  1. 당신이 사용하는 비동기 방법 모든 방법입니다.
  2. 리 작업입니다.지연 시간은 정확하지 않습니다.On my PC,작업입니다.지연(1)실제로 대기~20ms.

오 남자,이들 중 일부는 받은 엄청나게 복잡합니다.당신이해야 할 모든 것을 확인 BackgroundWorker.CancellationPending 는 시설 내에면서 처리기입니다.당신은 그것을 확인할 수 있습니다.면 보류 중인 설정하자.Cancel=True 및석에서 방법입니다.

//method 여기에서 private void Worker_DoWork(객체를 보낸 사람,DoWorkEventArgs e) { BackgroundWorker bw=(으로 보낸 사람을 BackgroundWorker);

// do stuff

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

// do other stuff

}

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top