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
때문에 반드시 인스턴스를 만든 스레드에서 실행되지 않습니다, 내가 만드는 스레드가 IncrementCounter
CompleteAsyncWork
동안 호출 될 가능성이 있다고 믿고있어 실행 중입니다. 이 경우 RunWorkerCompletedHandler
의 멤버 변수를 수정해도 안전합니까? 그렇지 않다면 올바른 접근 방식은 무엇입니까?
현재 GUI 스레드에 있는지 확인하는 빠른 검사가 있습니까? 나는'InvokeRequired'에 대해 읽었지 만 그것은 컨트롤에 대한 액세스 권한이 필요합니다. – Pieter
BGW를 생성하는 코드는 주 스레드에서 이미 확인할 필요가 있으므로 확인할 필요가 없습니다. 그렇지 않으면, 컨트롤 또는 어쩌면 동기화 컨텍스트를 잡아. –
"이미 알고있을 것"이란 무엇을 의미합니까? GUI 스레드에서 인스턴스를 작성해야한다는 것을 알고 있지만 실수로 다른 사람이이 원칙을 위반하지 않고 성가신 버그를 일으키지 않는다고 보장 할 수는 없습니다. 보통 디버그 어서션을 사용하여 어리 석음을 막아 문제를 쉽게 추적 할 수 있습니다. – Pieter