我无法弄清楚使用RunWorkerCompletedHandler
s的线程安全问题。我在Stack Overflow上的其他地方找到了这个:
如果在UI线程上创建了BackgroundWorker,DoWork将在线程池线程上运行,RunWorkerCompleted将在UI线程上运行。
如果在后台线程(即不是UI线程)上创建BackgroundWorker,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
中的成员变量是否安全?如果不是,那么正确的方法是什么?
答案 0 :(得分:2)
如果不是,那么正确的方法是什么?
正确的方法是仅在主GUI线程上创建BGW。它们在任何其他方面都没有多大用处。