2013-07-30 3 views
0

RunWorkerCompletedHandler을 사용하는 스레드 안전성의 영향을 파악하는 데 문제가 있습니다. 스택 오버플로의 다른 위치에서 이것을 찾았습니다.RunWorkerCompletedHandlers의 스레드 안전

UI 스레드에서 BackgroundWorker를 만들면 DoWork가 스레드 풀 스레드에서 실행되고 RunWorkerCompleted가 UI 스레드에서 실행됩니다.

BackgroundWorker가 백그라운드 스레드 (UI 스레드가 아님)에서 작성된 경우 DoWork는 여전히 스레드 풀 스레드에서 실행되고 RunWorkerCompleted는 스레드 풀 스레드에서도 실행됩니다. 다음 클래스 감안할 때

:

class TestingClass 
{ 
    private BackgroundWorker _bgWorker = new BackgroundWorker(); 
    private int _counter = 0; 

    private readonly int _creatorID; 

    public TestingClass() 
    { 
     _creatorID = Environment.CurrentManagedThreadId; 

     _bgWorker.DoWork += DoAsyncWork; 
     _bgWorker.RunWorkerCompleted += CompleteAsyncWork; 
     _bgWorker.RunWorkerAsync(); 
    } 

    public void IncrementCounter() 
    { 
     // We only allow the creator of this instance to call this function 
     // because instances of this class will not be shared with other threads. 
     Debug.Assert(_creatorID == Environment.CurrentManagedThreadId); 

     ++_counter; 
    } 

    private void DoAsyncWork(object sender, DoWorkEventArgs e) 
    { 
     int i = 0; 
     while (i < 100000) 
      ++i; 
    } 

    private void CompleteAsyncWork(object sender, RunWorkerCompletedEventArgs e) 
    { 
     // Apparently _creatorID == Environment.CurrentManagedThreadId isn't guaranteed here! 

     // Modification of member variable after the asynchronous part 
     // has been completed. 
     ++_counter; 
    } 
} 

CompleteAsyncWork 때문에 반드시 인스턴스를 만든 스레드에서 실행되지 않습니다, 내가 만드는 스레드가 IncrementCounterCompleteAsyncWork 동안 호출 될 가능성이 있다고 믿고있어 실행 중입니다. 이 경우 RunWorkerCompletedHandler의 멤버 변수를 수정해도 안전합니까? 그렇지 않다면 올바른 접근 방식은 무엇입니까?

답변

2

아니요, 올바른 접근 방법은 무엇입니까?

올바른 방법은 기본 GUI 스레드에서만 BGW를 만드는 것입니다. 다른 방법으로는별로 쓸모가 없습니다.

+0

현재 GUI 스레드에 있는지 확인하는 빠른 검사가 있습니까? 나는'InvokeRequired'에 대해 읽었지 만 그것은 컨트롤에 대한 액세스 권한이 필요합니다. – Pieter

+0

BGW를 생성하는 코드는 주 스레드에서 이미 확인할 필요가 있으므로 확인할 필요가 없습니다. 그렇지 않으면, 컨트롤 또는 어쩌면 동기화 컨텍스트를 잡아. –

+0

"이미 알고있을 것"이란 무엇을 의미합니까? GUI 스레드에서 인스턴스를 작성해야한다는 것을 알고 있지만 실수로 다른 사람이이 원칙을 위반하지 않고 성가신 버그를 일으키지 않는다고 보장 할 수는 없습니다. 보통 디버그 어서션을 사용하여 어리 석음을 막아 문제를 쉽게 추적 할 수 있습니다. – Pieter