Как дождаться окончания работы BackgroundWorker и затем выйти из консольного приложения - PullRequest
17 голосов
/ 22 сентября 2010

Я написал пример консольного приложения для тестирования backgroundworker, используя один из примеров, размещенных здесь в Stackoverflow.У меня есть фоновый работник, который начинается с основного метода, но заканчивается в середине операции, если я нажимаю клавишу ввода, потому что я написал console.readkey в основном методе.Но я хочу, чтобы он подождал, пока фоновый работник закончил делать работу, а затем вышел из приложения.Это мой код.

class Program
{
    private static BackgroundWorker worker = new BackgroundWorker();
    private event EventHandler BackgroundWorkFinished;

    static void Main(string[] args)
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;
        worker.WorkerSupportsCancellation = true;

        Console.WriteLine("Starting Application...");

        worker.RunWorkerAsync();
        Console.ReadKey();
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage.ToString());
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Starting to do some work now...");
        int i;
        for (i = 1; i < 10; i++)
        {
            Thread.Sleep(1000);
            worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
        }

        e.Result = i;
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Value Of i = " + e.Result.ToString());
        Console.WriteLine("Done now...");
    }
}

Ответы [ 3 ]

9 голосов
/ 22 сентября 2010

См. Как ждать отмены BackgroundWorker? о том, как установить связь между вашим BackgroundWorker и вашим основным потоком.

По сути, вы должны использовать событие, которое вы установили в конце DoWork, чтобы сигнализировать о завершении DoWork. Вы затем WaitOne () для этого события в вашем основном потоке.

4 голосов
/ 22 сентября 2010

Основная цель Bgw - взаимодействие с Windows MessageQueue.Другими словами, это наиболее полезно в приложениях WinForms и WPF.

Консольное приложение не подходит для использования или тестирования Bgw.Вы получите странные результаты.Напечатайте ManagedThreadId в ключевых точках, чтобы увидеть, что происходит.

И несколько стандартных советов: ваш worker_RunWorkerCompleted() должен проверить e.Error. Сейчас это то же самое, что и пустой блок catch{}.
Любая ошибка из DoWork теперь будет выдаваться при чтении e.Result, более сложном для обработки.

2 голосов
/ 22 сентября 2010

Это то, что я сделал сейчас.Но console.readkey() не работает.Приложение не ожидает функцию ReadKey().

class Program
{
    private static BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();
    private static AutoResetEvent resetEvent = new AutoResetEvent(false);
    static void Main(string[] args)
    {
        worker.DoWork += worker_DoWork;
        worker.RunWorkerCompleted += worker_RunWorkerCompleted;
        worker.ProgressChanged += worker_ProgressChanged;
        worker.WorkerReportsProgress = true;

        Console.WriteLine("Starting Application...");

        worker.RunWorkerAsync();
        resetEvent.WaitOne();

        Console.ReadKey();
    }

    static void worker_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
        Console.WriteLine(e.ProgressPercentage.ToString());
    }

    static void worker_DoWork(object sender, DoWorkEventArgs e)
    {
        Console.WriteLine("Starting to do some work now...");
        int i;
        for (i = 1; i < 10; i++)
        {
            Thread.Sleep(1000);
            worker.ReportProgress(Convert.ToInt32((100.0 * i) / 10));
        }

        e.Result = i;

        resetEvent.Set();
    }

    static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
        Console.WriteLine("Value Of i = " + e.Result.ToString());
        Console.WriteLine("Done now...");
    }

}

Исправление Редактирование: Перемещено resetEvent.Set() внутрь DoWork , а не в RunWorkerCompleted.Обработчик события Completed никогда не будет вызван, потому что основной поток ожидает событие.

...