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

22

我编写了一个样例控制台应用程序来测试使用Stackoverflow中发布的示例之一来进行背景工作。我有一个backgroundworker,在主方法中启动,但如果我按下enter键,它会在操作中间结束,因为我在主方法中写了console.readkey。但是我希望它等待backgroundworker完成工作后再退出应用程序。这是我的代码。

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...");
    }
}

1
为什么你要运行后台进程Async?看起来你想让它同步运行... - Jaco Pretorius
1
如何同步运行它..??? - Soham Dasgupta
1
可能是重复的问题:如何等待BackgroundWorker取消? - Aoi Karasu
3个回答

12

请参考如何等待BackgroundWorker取消?一文,了解如何在BackgroundWorker和主线程之间进行通信。

基本上,您需要在DoWork的结尾设置一个事件来表示DoWork已完成。然后,在主线程中使用WaitOne()等待该事件。


我已将新代码添加为答案。但仍存在一些问题,请帮忙。 - Soham Dasgupta

4
主要目的是与Windows消息队列交互。换句话说,在WinForms和WPF应用程序中使用最为实用。
控制台应用程序不是使用或测试Bgw的正确位置。你会得到奇怪的结果。在关键点打印ManagedThreadId以查看发生了什么。
还有一些标准建议:您的worker_RunWorkerCompleted()应该检查e.Error。现在它与一个空的catch{}块相同。
任何来自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...");
    }

}

修复编辑:resetEvent.Set()移到DoWork内部,而不是在RunWorkerCompleted中。由于主线程正在等待事件,因此完成事件处理程序永远不会被调用。


如果我在Windows 7上使用带有.NET 3.5 SP1的VS2008控制台项目中使用此代码,它对我有效。 - Andreas Paulsson
2
修复了代码。你必须在DoWork函数内部调用event.Set() - Ian Boyd

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接