В моей программе у меня есть два метода, выполнение которых занимает некоторое время, около нескольких минут каждый. Пока эти методы выполняются, я отображаю индикатор выполнения в отдельном окне, который показывает ход выполнения каждого метода. Мои два метода находятся в статическом классе Utility. Они выглядят следующим образом:
public static class Utility
{
public static bool TimeConsumingMethodOne(object sender)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(100);
(sender as BackgroundWorker).ReportProgress(i);
}
return true;
}
public static bool TimeConsumingMethodTwo(object sender)
{
for (int i = 1; i <= 100; i++)
{
Thread.Sleep(50);
(sender as BackgroundWorker).ReportProgress(i);
}
return true;
}
}
Прочитав похожие вопросы в SO, я узнал, что должен использовать BackgroundWorker и использовать RunWorkerCompleted(), чтобы увидеть, когда рабочий завершит свою работу. Итак, в моем Main() я использовал BackgroundWorer() и подписался на метод RunWorkerCompleted(). Моя цель здесь - сначала запустить TimeConsumingMethodOne() (и отобразить прогресс во время работы), затем после завершения запустить TimeConsumingMethodTwo() и снова показать прогресс, а когда это будет завершено, вывести окно сообщения (которое имитирует некоторые другие работы в моей программе) . Мой Main() выглядит следующим образом:
public partial class MainWindow : Window
{
public enum MethodType
{
One,
Two
}
private BackgroundWorker worker = null;
private AutoResetEvent _resetEventOne = new AutoResetEvent(false);
private AutoResetEvent _resetEventTwo = new AutoResetEvent(false);
private ProgressBarWindow pbWindowOne = null;
private ProgressBarWindow pbWindowTwo = null;
public MainWindow()
{
InitializeComponent();
}
private void btnRun_Click(object sender, RoutedEventArgs e)
{
RunMethodCallers(sender, MethodType.One);
_resetEventOne.WaitOne();
RunMethodCallers(sender, MethodType.Two);
_resetEventTwo.WaitOne();
MessageBox.Show("COMPLETED!");
}
private void RunMethodCallers(object sender, MethodType type)
{
worker = new BackgroundWorker();
worker.WorkerReportsProgress = true;
switch (type)
{
case MethodType.One:
worker.DoWork += MethodOneCaller;
worker.ProgressChanged += worker_ProgressChangedOne;
worker.RunWorkerCompleted += worker_RunWorkerCompletedOne;
break;
case MethodType.Two:
worker.DoWork += MethodTwoCaller;
worker.ProgressChanged += worker_ProgressChangedTwo;
worker.RunWorkerCompleted += worker_RunWorkerCompletedTwo;
break;
}
worker.RunWorkerAsync();
}
private void MethodOneCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowOne = new ProgressBarWindow("Running Method One");
pbWindowOne.Owner = this;
pbWindowOne.Show();
});
Utility.TimeConsumingMethodOne(sender);
}
private void MethodTwoCaller(object sender, DoWorkEventArgs e)
{
Dispatcher.Invoke(() =>
{
pbWindowTwo = new ProgressBarWindow("Running Method Two");
pbWindowTwo.Owner = this;
pbWindowTwo.Show();
});
Utility.TimeConsumingMethodTwo(sender);
}
private void worker_RunWorkerCompletedOne(object sender, RunWorkerCompletedEventArgs e)
{
_resetEventOne.Set();
}
private void worker_RunWorkerCompletedTwo(object sender, RunWorkerCompletedEventArgs e)
{
_resetEventTwo.Set();
}
private void worker_ProgressChangedOne(object sender, ProgressChangedEventArgs e)
{
pbWindowOne.SetProgressUpdate(e.ProgressPercentage);
}
private void worker_ProgressChangedTwo(object sender, ProgressChangedEventArgs e)
{
pbWindowTwo.SetProgressUpdate(e.ProgressPercentage);
}
}
Теперь у меня проблема: когда я использую _resetEventOne.WaitOne(); пользовательский интерфейс зависает. Если я уберу эти два ожидания, оба метода будут работать асинхронно, а выполнение продолжится и выведет MessageBox еще до завершения этих двух методов.
Что я делаю неправильно? Как мне заставить программу завершить мой первый BackgroundWorker, а затем перейти к следующему, а затем, когда это будет сделано, вывести MessageBox?