Подтвердить что ты не робот

Как дождаться завершения BackgroundWorker, а затем выйти из консольного приложения

Я написал пример консольного приложения для тестирования фонового рабочего, используя один из примеров, размещенных здесь в Stackoverflow. У меня есть работник backgroundwork, который начинается с основного метода, но заканчивается в середине операции, если я нажимаю кнопку ввода, потому что я написал файл 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...");
    }
}
4b9b3361

Ответ 1

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

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

Ответ 2

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

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

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

Ответ 3

Это то, что я сделал сейчас. Но 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...");
    }

}

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