Jiew Meng

Web Developer, Computer Science Student

Posts tagged "async"

C#: Using The BackgroundWorker for Time Consuming/Blocking Tasks

Suppose you have some time-consuming “very useful” function like below

for (var i = 1; i <= 10; i++)
{
    Thread.Sleep(TimeSpan.FromMilliseconds(i * 200));
}

If it runs on the UI thread, you will get a “hanged” UI (you can’t click buttons, drag the window etc). To fix that, you can use a BackgroundWorker, its easy. There are 3 main events that you need to handle

  • DoWork - where all your processing code will go
  • ProgressChanged - to do something when progress changes. eg. update progress bar
  • RunWorkerCompleted - triggered when background operation (DoWork) has completed, been canceled or raise an exception

The code below is very simple and self-explanatory, ask me in the comments if you have any questions

public MainWindow()
{
    InitializeComponent();

    #region Worker Stuff
    _worker = new BackgroundWorker();
    _worker.WorkerReportsProgress = true;
    _worker.WorkerSupportsCancellation = true;

    // Where your useful, time-consuming, blocking code will go
    _worker.DoWork += (s, args) =>
    {
        for (var i = 1; i <= 10; i++)
        {
            // handle the cancelation of the task
            if (_worker.CancellationPending) 
            {
                args.Cancel = true;
                return;
            }
            _worker.ReportProgress(i * 10);
            Thread.Sleep(TimeSpan.FromMilliseconds(i * 200));
        }
        args.Result = "Done!";
    };

    // As progress is changed, update the UI
    _worker.ProgressChanged += (s, args) =>
    {
        progBar.Value = args.ProgressPercentage;
        txtLog.Text = args.ProgressPercentage + "%";
    };

    // Handle when the worker is canceled, raises an exception or completes 
    _worker.RunWorkerCompleted += (s, args) =>
    {
        if (args.Cancelled)
            txtLog.Text = "Canceled";
        else if (args.Error != null)
            txtLog.Text = args.Error.Message;
        else
            txtLog.Text = args.Result.ToString();
    };
    #endregion
}

private void Button_Click(object sender, RoutedEventArgs e)
{
    _worker.RunWorkerAsync(); // Starts running code in DoWork()
}

private void Button_Click_1(object sender, RoutedEventArgs e)
{
    _worker.CancelAsync(); // Cancel the operation. BackgroundWorker.CancelationPending will be set to true
}

A video showing the outcome,

Source Code: on MediaFire

Search

Loading

Likes

Following