views:

170

answers:

4

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...");
    }
}
+3  A: 

What you can do here is:

worker.RunWorkerAsync();

while (worker.IsBusy)
{
  // do nothing or sleep for a few ms
}
Console.ReadLine(); // not readkey

Edit: See the comments for better suggestions on production usage.

leppie
Remember to put that sleep command inside the loop, else this process will consume most of your CPU power looping as fast as it can. Even Sleep(1) will help this.
Øyvind Bråthen
Please, no busy wait loop (not even with a sleep in it). Use e.g. AutoResetEvent instead and WaitOne.
Andreas Paulsson
-1 for using a endless wait loop instead some kind of Event mechanism
Oliver
@Andreas Paulsson: Agreed for production code, but for simple test. Guess I been doing too much embedded stuff lately :)
leppie
+2  A: 

The main purpose of a Bgw is to interact with the MessageQueue.

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.

Henk Holterman
+3  A: 

See the http://stackoverflow.com/questions/123661/net-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.

Andreas Paulsson
I've added the new code as an answer. But there is still some problem. Please help.
Soham Dasgupta
A: 

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;
        }

        static void worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            Console.WriteLine("Value Of i = " + e.Result.ToString());
            Console.WriteLine("Done now...");
            resetEvent.Set();
        }

    }
Soham Dasgupta
If I use this code in a Console Project in VS2008 with .NET 3.5 SP1 on Windows 7, it works for me.
Andreas Paulsson
Doesn't work for me in VS2008 in Windows XP.
Soham Dasgupta
Please help....
Soham Dasgupta