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

C# 如何等待BackgroundWorker完成,然后退出控制台应用程序,c#,.net,multithreading,backgroundworker,C#,.net,Multithreading,Backgroundworker,我已经编写了一个示例控制台应用程序,使用Stackoverflow中发布的一个示例测试backgroundworker。我有一个后台工作人员,它从主方法开始,但是如果我按回车,它就结束在操作的中间,因为我已经在主方法中编写了一个控制台。但我希望它等到后台工作人员完成工作后再退出应用程序。这是我的密码 class Program { private static BackgroundWorker worker = new BackgroundWorker(); private ev

我已经编写了一个示例控制台应用程序,使用Stackoverflow中发布的一个示例测试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...");
    }
}
类程序
{
private static BackgroundWorker worker=new BackgroundWorker();
私有事件EventHandler后台工作已完成;
静态void Main(字符串[]参数)
{
worker.DoWork+=worker\u DoWork;
worker.RunWorkerCompleted+=worker\u RunWorkerCompleted;
worker.ProgressChanged+=worker\u ProgressChanged;
worker.WorkerReportsProgress=true;
worker.worker支持扫描单元=true;
Console.WriteLine(“启动应用程序…”);
worker.RunWorkerAsync();
Console.ReadKey();
}
静态无效工作程序\u ProgressChanged(对象发送器,ProgressChangedEventArgs e)
{
Console.WriteLine(例如ProgressPercentage.ToString());
}
静态无效工作线程(对象发送器,工作线程)
{
WriteLine(“现在开始做一些工作…”);
int i;
对于(i=1;i<10;i++)
{
睡眠(1000);
工人报告进度(转换为32((100.0*i)/10));
}
e、 结果=i;
}
静态无效工作程序\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
Console.WriteLine(“i的值=“+e.Result.ToString());
Console.WriteLine(“现在完成…”);
}
}

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

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

还有一些标准建议:您的
worker\u RunWorkerCompleted()
应该检查
e.Error
。现在它与拥有一个空的
catch{}
块是一样的
当您读取
e.Result
时,DoWork中的任何错误现在都将抛出,处理起来更复杂

有关如何在后台工作人员和主线程之间进行通信,请参阅帖子


基本上,您必须使用在DoWork结束时设置的事件来表示DoWork已完成。然后在主线程中等待该事件的处理。

这就是我现在所做的。但是
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...");
    }

}
类程序
{
private static BackgroundWorker worker=new System.ComponentModel.BackgroundWorker();
私有静态AutoResetEvent resetEvent=新的AutoResetEvent(假);
静态void Main(字符串[]参数)
{
worker.DoWork+=worker\u DoWork;
worker.RunWorkerCompleted+=worker\u RunWorkerCompleted;
worker.ProgressChanged+=worker\u ProgressChanged;
worker.WorkerReportsProgress=true;
Console.WriteLine(“启动应用程序…”);
worker.RunWorkerAsync();
resetEvent.WaitOne();
Console.ReadKey();
}
静态无效工作程序\u ProgressChanged(对象发送器,ProgressChangedEventArgs e)
{
Console.WriteLine(例如ProgressPercentage.ToString());
}
静态无效工作线程(对象发送器,工作线程)
{
WriteLine(“现在开始做一些工作…”);
int i;
对于(i=1;i<10;i++)
{
睡眠(1000);
工人报告进度(转换为32((100.0*i)/10));
}
e、 结果=i;
resetEvent.Set();
}
静态无效工作程序\u RunWorkerCompleted(对象发送方,RunWorkerCompletedEventArgs e)
{
Console.WriteLine(“i的值=“+e.Result.ToString());
Console.WriteLine(“现在完成…”);
}
}

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

我添加了新代码作为答案。但仍然存在一些问题。请帮助。为什么要异步运行后台进程?似乎您希望它同步运行…如何同步运行..???如果我在VS2008的控制台项目中使用此代码,并在Windows 7上使用.NET 3.5 SP1,则可能重复此代码。修复了此代码。您必须从DoWork内部调用
event.Set()