如何等待BackgroundWorker完成然后退出控制台应用程序

时间:2010-09-22 09:16:28

标签: c# .net multithreading backgroundworker

我已经使用Stackoverflow中发布的示例之一编写了一个示例控制台应用程序来测试backgroundworker。我有一个backgroundworker,它以main方法开头,但是如果我按下回车键,它会在操作过程中结束,因为我在main方法中写了一个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 个答案:

答案 0 :(得分:9)

请参阅How to wait for a BackgroundWorker to cancel?帖子,了解如何在BackgroundWorker与主线程之间进行通信。

基本上,您必须使用在DoWork结束时设置的事件来表示DoWork已完成。然后在主线程中对该事件进行WaitOne()。

答案 1 :(得分:4)

Bgw的主要目的是与Windows MessageQueue交互。换句话说,它在WinForms和WPF应用程序中最有用。

控制台应用程序不是使用或测试Bgw的正确位置。你会得到奇怪的结果。在关键点打印ManagedThreadId,看看会发生什么。

以及一些标准建议:您的worker_RunWorkerCompleted()应该检查e.Error现在它与空catch{}块相同。
当您阅读e.Result时,将会抛出来自DoWork的任何错误,处理起来更复杂。

答案 2 :(得分:2)

这就是我现在所做的。但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 已完成事件处理程序永远不会被调用,因为主线程正在等待事件。