让我感到困惑的一件事是,BackgroundWorker似乎对周围类的实例变量进行了线程安全访问。
给出基本课程:
public class BackgroundProcessor
{
public List<int> Items { get; private set; }
public BackgroundProcessor(IEnumerable<int> items)
{
Items = new List<int>(items);
}
public void DoWork()
{
BackgroundWorker worker = new BackgroundWorker();
worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(worker_RunWorkerCompleted);
worker.DoWork += new DoWorkEventHandler(worker_DoWork);
worker.RunWorkerAsync();
}
void worker_DoWork(object sender, DoWorkEventArgs e)
{
var processor = new ProcessingClass();
processor.Process(this.Items); //Accessing the instance variable
}
void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
//Stuff goes here
}
}
在我的假设中我是否错误地调用processor.Process(this.Points);
是一个线程安全的呼叫?我怎么不得到跨线程访问冲突?
我确信这很明显,但它总是让我困惑。
答案 0 :(得分:6)
它不是线程安全的,只是看起来那样。您只能获得GUI控件的跨线程异常。很难要求只能从创建GUI控件的线程访问GUI控件。因此框架花时间检查来自其他线程的调用。请注意,这实际上与同步问题正交(至少从我们的角度来看,而不是从USER子系统的角度来看),因为您仍然可以使用锁来防止多个线程同时访问控件而且仍然违反跨线程。
由于成员变量不是GUI控件,因此不检查跨线程调用,也不检查竞争条件。你必须自己使用锁定或其他机制。除非集合类被破坏,否则不会有异常。我不相信它们是线程安全的,但我不确定这最终意味着什么,我也没有在同时运行的线程之间共享那些变量,所以我实际上没有遇到问题。可以这么说,做正确的事情比希望集合类神奇地工作更好。
答案 1 :(得分:0)
后台工作程序是一种在不同线程上启动进程的简单方法,它不会为您提供线程安全。
如果您只是阅读后台工作人员已经更改过的变量,那就没问题了。