programing

백그라운드 작업자를 완전히 "죽이는"방법은 무엇입니까?

yoursource 2021. 1. 14. 23:24
반응형

백그라운드 작업자를 완전히 "죽이는"방법은 무엇입니까?


일련의 디지털 IO 작업을 반복적으로 실행하는 Windows 응용 프로그램을 작성 중입니다.

이 일련의 작업은 사용자가 "START"버튼을 클릭 할 때 시작되며 backgroundWorker1_DoWork ()의 ​​백그라운드 작업자가 수행합니다.

그러나 "이 백그라운드 작업자가 현재 사용 중입니다 ......."오류 메시지가 표시되는 경우가 있습니다.

다른 작업 시퀀스를 시작하기 전에 백그라운드 작업자를 "종료"하기 위해 while 루프를 사용하여 코드에서 다음을 구현할 생각입니다.

if (backgroundWorker1.IsBusy == true)
{

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

    backgroundWorker1.Dispose();

}

backgroundWorker1.RunWorkerAsync();

내 주요 관심사는 backgroundWorker1이 결국 "죽이는"것입니다. 그렇다면 완료하는 데 시간이 오래 걸리나요?

이 코딩으로 인해 무한 루프가 발생합니까?


다음과 같은 것을 사용할 수 있습니다 (관리되는 스레드 중단 및 ThreadAbortException에 대한 자세한 내용은 Chris Sells의 " Rotor를 사용하여 ThreadAbortException의 깊이 연결 "참조 ).

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

나는 스레드가 자신의 수명을 포함하여 실행 가능한 한 자신 리소스에 대해 책임을 져야한다고 생각합니다 .

일반적으로 범위 밖에서 스레드를 죽이는 것은 나쁜 생각입니다. 자체적 으로 종료되도록 스레드에 메시지를 전달하도록 설계된 응용 프로그램은 다중 스레드 동작과 관련된 문제가 훨씬 적습니다.

스레드는 해당 메시지를 모니터링해야합니다.이 메시지는 다른 스레드에서 설정 한 부울처럼 간단하고 해당 모니터링 스레드에서 읽을 수 있으며 가능한 한 빨리 완전히 종료됩니다 .

즉, 메시지를 찾아야하는 경우 :

  • 메인 루프 (있는 경우)입니다.
  • 장기 실행 루프에서 주기적으로.

메시지와 함께 종료하는 스레드는 기다려야합니다 (물론 GUI를 중지하지 마십시오).

외부 킬링이 더 안전 해 지도록 스레드가 스스로 취소 가능으로 표시 할 수있는 경우와 같이 특정 기능이있는 스레드 환경에 대한 다른 가능성이 있습니다.

그러나 일반적으로 자신의 운명에 맞는 스레드 마스터를 남기도록 애플리케이션을 설계하는 것이 더 쉽습니다.


I put one together that (i think) does the job. Please let me know if im waaaay off. Here is a simple exaple of how it works.

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

Since the background worker is part of the thread pool, we dont want to abort it. But we can run a thread internally which we can allow an abort to occur on. The backgroundWorker then basically runs until either the child thread is complete or we signal to it to kill the process. The background worker thread can then go back into the read pool. Typically I will wrap this up in a helper class and pass through the delegate method that I want the background thread to run passed in as the parameter and run that in the child thread.

Please someone let me know if im banging my head against a wall but it seems to work fine.. But thats the problem with threads isnt it.. the varying results you can get when you run it at different times.


I was having the same problem, I'm not sure if this will help but I'm guessing your background worker has a loop within or it would exit. What you need to do is put your loop within.

Put inside your background worker:

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

To kill this backgroundworker, you can put in your button:

BackgroundWorker1.CancelAsync()

I hope this helps.


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

    }



}

you set kill to true to kill the thread and no abort problem :)

ReferenceURL : https://stackoverflow.com/questions/800767/how-to-kill-background-worker-completely

반응형