Я работаю над асинхронной операцией, которая должна вызывать дальнейшие асинхронные задачи. Я пытаюсь упростить его с помощью BackgroundWorkers, в результате чего один обратный вызов BackgroundWorker's 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));
}
}
Итак, проблема в том, что я ожидаю, что Class2._Worker_RunWorkerCompleted () будет выполняться в том же потоке, в котором был вызван Class2.DoSomethingElseAsync (). Этого никогда не происходит - вместо этого обратный вызов выполняется в совершенно новом потоке.
Вот мое подозрение: _worker_DoWork () класса 1 никогда не возвращается, что означает, что поток никогда не вернется к слушателю событий, даже если он существует (я подозреваю, что нет). С другой стороны, если _worker_DoWork () вернулось, BackgroundWorker Class1 автоматически завершит работу преждевременно - ему нужно дождаться завершения работы Class2, прежде чем он сможет завершить свою работу.
Это приводит к двум вопросам:
- Правильно ли мое подозрение?
- Каков наилучший способ вложения таких асинхронных операций? Могу ли я спасти подход BackgroundWorker или есть какой-то другой, более подходящий метод?