Sea*_*n U 4 c# multithreading backgroundworker
我正在进行需要调用更多异步任务的异步操作.我试图通过使用BackgroundWorkers来保持简单,结果是一个BackgroundWorker的DoWork()回调调用一个创建第二个BackgroundWorker的方法,就像这样(减去错误检查和所有爵士乐的简洁):
class Class1
{
private BackgroundWorker _worker = null;
public void DoSomethingAsync()
{
_worker = new BackgroundWorker();
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.RunWorkerAsync();
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
Class2 foo = new Class2();
foo.DoSomethingElseAsync();
while(foo.IsBusy) Thread.Sleep(0); // try to wait for foo to finish.
}
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
// do stuff
}
}
class Class2
{
private BackgroundWorker _worker = null;
Thread _originalThread = null;
public AsyncCompletedEventHandler DoSomethingCompleted;
public bool IsBusy { get { return _worker != null && _worker.IsBusy; } }
public void DoSomethingElseAsync()
{
_originalThread = Thread.CurrentThread;
_worker = new BackgroundWorker();
_worker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(_worker_RunWorkerCompleted);
_worker.DoWork += new DoWorkEventHandler(_worker_DoWork);
_worker.RunWorkerAsync();
}
void _worker_DoWork(object sender, DoWorkEventArgs e)
{
// do stuff
}
void _worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
Debug.Assert(Thread.CurrentThread == _originalThread); // fails
// Assuming the above Assert() were excluded, the following event would be raised on the wrong thread.
if (DoSomethingCompleted != null) DoSomethingCompleted(this, new AsyncCompletedEventArgs(e.Error, e.Cancelled, null));
}
}
Run Code Online (Sandbox Code Playgroud)
所以问题是,我期望Class2._Worker_RunWorkerCompleted()在调用Class2.DoSomethingElseAsync()的同一个线程上执行.这种情况从未发生过 - 相反,回调运行在一个全新的线程上.
这是我的怀疑:Class1的_worker_DoWork()永远不会返回,这意味着线程永远不会回到事件监听器,即使存在一个(我怀疑没有).另一方面,如果_worker_DoWork()确实返回,Class1的BackgroundWorker会自动提前完成 - 它需要等待Class2完成工作才能完成其工作.
这导致了两个问题:
如果BackgroundWorker在UI线程上创建了a ,DoWork则将在线程池线程上RunWorkerCompleted运行,并将在UI线程上运行.
如果BackgroundWorker在后台线程(即不是UI线程)DoWork上创建a仍将在线程池线程上RunWorkerCompleted运行,并且还将在线程池线程上运行.
在您的情况下,由于您无法编组对任意(线程池)线程的调用,您将无法保证所需的行为,尽管您可能需要查看System.Threading.SynchronizationContext.