I have written a sample console application to test backgroundworker using one of the examples posted here in Stackoverflow. I have a backgroundworker which start with the main method but its ending in the middle of the operation if I press enter because I have written a console.readkey in the main method. But I want it to wait till the backgroundworker has finished doing the job then exit the application. This is my code.
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...");
}
}
See the How to wait for a BackgroundWorker to cancel? post for how to communicate between your BackgroundWorker and your main thread.
Basically, you have to use a event that you set at the end of DoWork to signal that DoWork has completed. You then WaitOne() on that event in your main thread.
The main purpose of a Bgw is to interact with the Windows MessageQueue. In other words it is most useful in WinForms and WPF applications.
A Console application is not the right place to use or test a Bgw. You'll get strange results. Print ManagedThreadId at the key points to see what happens.
And some standard advice: Your worker_RunWorkerCompleted()
should check e.Error
. Right now it is the same as having an empty catch{}
block.
Any error from DoWork will now be thrown when you read e.Result
, more complex to handle.
This is what I have done now. But the console.readkey()
is not working. The application is not waiting for the ReadKey()
function.
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...");
}
}
Fixing Edit: Moved resetEvent.Set()
to inside DoWork rather than in RunWorkerCompleted. The Completed event handler will never get called because the main thread is waiting for the event.
来源:https://stackoverflow.com/questions/3767827/how-to-wait-for-backgroundworker-to-finish-and-then-exit-console-application