Programming

BackgroundWorker 및 백그라운드 스레드

procodes 2020. 6. 1. 21:01
반응형

BackgroundWorker 및 백그라운드 스레드


Windows Form 앱에서 사용해야하는 백그라운드 스레드 구현의 선택에 대한 문체 질문이 있습니다. 현재 BackgroundWorker무한 (while(true))루프 가있는 양식이 있습니다 . 이 루프에서는 WaitHandle.WaitAny관심있는 일이 발생할 때까지 스레드를 다시 알림을 유지하는 데 사용합니다. 내가 기다리는 이벤트 핸들 중 하나는 " StopThread"이벤트이므로 루프에서 벗어날 수 있습니다. 이 이벤트는 재정의 된 시점에서 알립니다 Form.Dispose().

어디 선가 읽은 BackgroundWorker항목의 순서를 파일을 다운로드하거나 처리와 같은 - 당신이 UI를 묶어과 유한 끝을 갖고 싶어하지 않는 것이 정말 작업을위한 것입니다을. 이 경우 "종료"는 알 수 없으며 창을 닫을 때만 가능합니다. 따라서이 BackgroundWorker목적 대신 배경 스레드를 사용하는 것이 더 적절 합니까?


귀하의 질문에 대한 나의 이해 BackgroundWorker에서 표준 스레드로 사용하고 있습니다.

BackgroundWorkerUI 스레드를 묶고 싶지 않은 것들에 권장되는 이유 는 Win Forms 개발을 수행 할 때 멋진 이벤트가 노출되기 때문입니다.

같은 이벤트는 RunWorkerCompleted스레드가 그것을 할 필요가 무엇 완료되면 알리기 위해, 그리고 ProgressChanged스레드가 진행에 이벤트가 GUI를 업데이트 할 수 있습니다.

당신이 경우에 따라서 하지 않는 이들의 활용, 당신이해야 할 일에 대한 표준 스레드를 사용하여 어떤 해를 볼 수 없습니다.


내 생각 중 일부는 ...

  1. 백그라운드 에서 실행되는 단일 작업이 있고 UI와 상호 작용해야하는 경우 BackgroundWorker를 사용하십시오 . UI 스레드에 대한 데이터 마샬링 및 메서드 호출 작업은 이벤트 기반 모델을 통해 자동으로 처리됩니다. 다음과 같은 경우 BackgroundWorker를 피하십시오.
    • 어셈블리에 UI가 없거나 직접 상호 작용하지 않는 경우
    • 스레드가 포 그라운드 스레드 여야합니다. 또는
    • 스레드 우선 순위를 조작해야합니다.
  2. 효율성이 필요한 경우 ThreadPool 스레드를 사용하십시오 . ThreadPool은 스레드 작성, 시작 및 중지와 관련된 오버 헤드를 방지합니다. 다음과 같은 경우 ThreadPool을 사용하지 마십시오.
    • 작업은 애플리케이션 수명 동안 실행됩니다.
    • 스레드가 포 그라운드 스레드가되어야합니다.
    • 스레드 우선 순위를 조작하거나
    • 고정 된 ID (중지, 일시 중단, 발견)를 갖기 위해서는 스레드가 필요합니다.
  3. 장기 실행 작업 및 공식 스레딩 모델에서 제공하는 기능 (예 : 포 그라운드 및 백그라운드 스레드 선택, 스레드 우선 순위 조정, 스레드 실행에 대한 세밀한 제어 등)이 필요한 경우 Thread 클래스를 사용하십시오 .

Matt Davis가 말한 내용은 다음과 같습니다.

저에게있어 주요한 차별화 요소 BackgroundWorker는를 통해 완료된 이벤트를 자동으로 마샬링하는 것 SynchronizationContext입니다. UI 컨텍스트에서 이는 완료된 이벤트가 UI 스레드에서 발생하므로 UI를 업데이트하는 데 사용될 수 있음을 의미합니다. BackgroundWorkerUI 컨텍스트에서를 사용하는 경우 이는 주요 차별화 요소 입니다.

를 통해 실행 된 작업 ThreadPool은 쉽게 취소 할 수 없습니다 ( ThreadPool. QueueUserWorkItem및 대리자가 비동기 적으로 실행 포함 ). 따라서 스레드 스핀 업의 오버 헤드를 피하면서 취소가 필요한 경우 BackgroundWorker또는 UI를 사용하여 스레드를 스핀 업하고 참조를 유지하여 호출 할 수 있도록하십시오 Abort().


또한 백그라운드 워커의 수명 동안 스레드 풀 스레드를 묶습니다. 유한 한 수의 스레드 만 있으므로 문제가 될 수 있습니다. 앱에 스레드를 한 번만 만들고 백그라운드 작업자의 기능을 사용하지 않는 경우 backgroundworker / threadpool 스레드 대신 스레드를 사용한다고 말하고 싶습니다.


Windows Forms, WPF 또는 기타 기술을 사용하는지 여부에 관계없이 BackgroundWorker로 작업하는 것이 더 쉬운 경우도 있습니다. 이 사람들의 깔끔한 부분은 스레드가 실행되는 위치에 대해 너무 걱정할 필요없이 스레딩을 얻는 것입니다. 이는 간단한 작업에 좋습니다.

BackgroundWorker스레드 (클로징 앱, 사용자 취소)를 취소하려면 먼저 고려 사항을 사용하기 전에 스레드가 취소를 확인 해야하는지 또는 실행 자체에 추력을 결정 해야하는지 결정해야합니다.

BackgroundWorker.CancelAsync()설정합니다 CancellationPending으로 true는 지속적으로이를 확인하면 사용자가 취소 이러한 접근 방식의 경쟁 조건으로 끝날 수 있다는 것을 염두에 두어야하지만, 스레드가 테스트 이전에 완료에 다음 스레드 책임하지만, 더 아무것도하지 않습니다 CancellationPending.

Thread.Abort() 반면에 스레드 실행 내에서 해당 스레드를 강제로 취소하는 예외가 발생하므로이 예외가 실행 내에서 갑자기 발생하면 위험한 상황에주의해야합니다.

스레딩은 작업에 관계없이 추가로 읽으려면 매우 신중하게 고려해야합니다.

.NET Framework 관리 형 스레딩 모범 사례 의 병렬 프로그래밍


.NET을 알기 전에 스레드를 사용하는 방법을 알았으므로 BackgroundWorkers를 사용할 때 익숙해졌습니다. Matt Davis는 그 차이점을 탁월하게 요약했지만 코드가 수행하는 작업을 정확하게 이해하기가 더 어려워 디버깅이 더 어려워 질 수 있다고 덧붙였습니다. 스레드 풀에 작업을 제공하는 것보다 IMO라는 스레드 작성 및 종료에 대해 생각하는 것이 더 쉽습니다.

여전히 다른 사람의 게시물에 댓글을 달 수 없으므로 교각을 해결하기 위해 답변을 사용하는 순간적인 절름발이를 용서하십시오 7

Thread.Abort ()를 사용하지 마십시오. 대신, 이벤트에 신호를 보내고 신호를 받으면 스레드가 정상적으로 종료되도록 설계하십시오. Thread.Abort ()는 스레드 실행의 임의 지점에서 ThreadAbortException을 발생시킵니다. 이로 인해 고아 모니터, 손상된 공유 상태 등과 같은 모든 종류의 불행한 작업을 수행 할 수 있습니다. http://msdn.microsoft.com/en-us/library/system.threading.thread.abort.aspx


그것이 깨지지 않은 경우-농담 할 때까지 고치십시오 : 농담 :)

그러나 심각하게 BackgroundWorker는 아마도 이미 가지고있는 것과 매우 유사 할 것입니다. 처음부터 시작했다면 아마도 시간을 절약했을 것입니다. 그러나이 시점에서 나는 필요를 보지 못했습니다. 무언가가 작동하지 않거나 현재 코드를 이해하기 어렵다고 생각하지 않으면 내가 가진 것을 고수 할 것입니다.


The basic difference is, like you stated, generating GUI events from the BackgroundWorker. If the thread does not need to update the display or generate events for the main GUI thread, then it can be a simple thread.


A background worker is a class that works in a separate thread, but it provides additional functionality that you don't get with a simple Thread (like task progress report handling).

If you don't need the additional features given by a background worker - and it seems you don't - then a Thread would be more appropriate.


I want to point out one behavior of BackgroundWorker class that wasn't mentioned yet. You can make a normal Thread to run in background by setting the Thread.IsBackground property.

Background threads are identical to foreground threads, except that background threads do not prevent a process from terminating. [1]

You can test this behavoir by calling the following method in the constructor of your form window.

void TestBackgroundThread()
{
    var thread = new Thread((ThreadStart)delegate()
    {
        long count = 0;
        while (true)
        {
            count++;
            Debug.WriteLine("Thread loop count: " + count);
        }
    });

    // Choose one option:
    thread.IsBackground = false; // <--- This will make the thread run in background
    thread.IsBackground = true; // <--- This will delay program termination

    thread.Start();
}

When the IsBackground property is set to true and you close the window, then your application will terminate normaly.

But when the IsBackground property is set to false (by default) and you close the window, then just the window will disapear but the process will still keep running.

The BackgroundWorker class utilize a Thread that runs in the background.


What's perplexing to me is that the visual studio designer only allows you to use BackgroundWorkers and Timers that don't actually work with the service project.

It gives you neat drag and drop controls onto your service but... don't even try deploying it. Won't work.

Services: Only use System.Timers.Timer System.Windows.Forms.Timer won't work even though it's available in the toolbox

Services: BackgroundWorkers will not work when it's running as a service Use System.Threading.ThreadPools instead or Async calls

참고URL : https://stackoverflow.com/questions/1506838/backgroundworker-vs-background-thread

반응형