Using BackgroundWorker in Windows Forms Application

I created a simple Windows Forms project using C# while taking advantage of BackgroundWorker object to run task at backward thread.

You just have to change/alter only one method: "CallMeBackward" which is called at backward thread in the demo project.



using System;
using System.ComponentModel;
using System.Threading;

namespace BackgroundWorkerInWindowsFormsApp
{
    public partial class Form1 : System.Windows.Forms.Form
    {
        BackgroundWorker _backgroundWorker = new BackgroundWorker();
        
        /*============================================================================*/
        public Form1()
        {
            InitializeComponent();
            
            /*============================================================================*/
            _backgroundWorker.DoWork += new DoWorkEventHandler(BackgroundWorkerDoWorkEvent);
            _backgroundWorker.WorkerSupportsCancellation = true;

            ThreadPool.QueueUserWorkItem(_backgroundWorker.RunWorkerAsync);
            /*============================================================================*/
        }

        /*============================================================================*/
        void BackgroundWorkerDoWorkEvent(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker backgroundWorker = sender as BackgroundWorker;
            string argument = (string)e.Argument;
            e.Result = OnTimeConsumingOperation(backgroundWorker, argument);
        }
        /*============================================================================*/
        string OnTimeConsumingOperation(BackgroundWorker bw, string arg)
        {
            ThreadPool.QueueUserWorkItem(_ =>
            {
                CallMeBackward();
            });
            return string.Empty;
        }
        /*============================================================================*/
        void CallMeBackward()
        {
            for (var i = 0; i < 2000; i++)
            {
                counterLabel.Text = i.ToString();
                timerLabel.Text = DateTime.Now.ToLongTimeString();
            }
        }
        /*============================================================================*/
        protected override void Dispose(bool disposing)
        {
            _backgroundWorker.CancelAsync();
            _backgroundWorker.Dispose();
            /*============================================================================*/
            var timer = new System.Windows.Forms.Timer();
            timer.Tick += (obj, evt) =>
            {
                if (!_backgroundWorker.IsBusy)
                {
                    if (disposing && (components != null))
                    {
                        components.Dispose();
                    }
                    base.Dispose(disposing);
                }
            };
            timer.Start();            
        }

        /*============================================================================*/        
    }
}

UI elements are not thread-safe and should be accessed only on the thread that created them. Otherwise you'll get following error message:

Cross-thread operation not valid: Control 'richTextBox1' accessed from a thread other than the thread it was created on.

BackgroundWorker cannot intercept main thread for UI elements. You've to use main thread instead.

No comments:

Post a Comment