Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to wait for BackgroundWorker to finish and then exit console application

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...");
    }
}
like image 654
Soham Dasgupta Avatar asked Sep 22 '10 09:09

Soham Dasgupta


People also ask

How do I know if BackgroundWorker is completed?

Threading. Thread. Sleep(50); return doubleReturn; //doubleReturn is the value that is filled if the BackgroundWorker is complete.

Is BackgroundWorker threaded?

BackgroundWorker, is a component in . NET Framework, that allows executing code as a separate thread and then report progress and completion back to the UI.

How does BackgroundWorker work in VB net?

BackgroundWorker enables a simple multithreaded architecture for VB.NET programs. This is more reliable, and easier, than trying to handle threads directly. In the Toolbox pane, please double-click on the BackgroundWorker icon. This will add a BackgroundWorker1 instance to the tray at the bottom of the screen.

What is use of BackgroundWorker in C#?

BackgroundWorker makes the implementation of threads in Windows Forms. Intensive tasks need to be done on another thread so the UI does not freeze. It is necessary to post messages and update the user interface when the task is done.


3 Answers

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.

like image 143
Andreas Paulsson Avatar answered Nov 07 '22 23:11

Andreas Paulsson


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.

like image 4
Henk Holterman Avatar answered Nov 08 '22 01:11

Henk Holterman


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.

like image 3
Soham Dasgupta Avatar answered Nov 08 '22 00:11

Soham Dasgupta