22

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...");
    }
}
abatishchev
  • 98,240
  • 88
  • 296
  • 433
Soham Dasgupta
  • 5,061
  • 24
  • 79
  • 125

3 Answers3

12

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.

Community
  • 1
  • 1
Andreas Paulsson
  • 7,745
  • 3
  • 25
  • 31
4

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.

H H
  • 263,252
  • 30
  • 330
  • 514
3

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.

Manos Nikolaidis
  • 21,608
  • 12
  • 74
  • 82
Soham Dasgupta
  • 5,061
  • 24
  • 79
  • 125