none
Backgroud worker how to dispose and confirm

    Question

  • I am having three quires regarding BackgroundWorker(BGW)

    1. I have started a single BGW and called bg.dispose() method after that if we check bg.Isbusy it is giving true. Why does this happen it should give false what is expected.

    2. If bg.dispose() is not used to kill BGW then how to kill and confirm this?

    3. How to dispose a BGW after particular time (for long running processes close BGW after 5 sec)?

    Please use the below code to help me out .

    namespace ConsoleApplication2
    {
        class Program
        {
            static void Main(string[] args)
            {
                BackgroundWorker bg = new BackgroundWorker();
                bg.DoWork += new DoWorkEventHandler(bgw_DoWork);
                bg.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgw_RunWorkerCompleted);
                bg.WorkerSupportsCancellation = true;
                bg.RunWorkerAsync();
                Console.WriteLine("BG started");
                Thread.Sleep(1000);
              
                bg.Dispose();
                if (bg == null)
                {
                    Console.WriteLine("false");
                }
                bool bgworking = bg.IsBusy;
                Console.WriteLine(bgworking);
                Console.ReadLine();
            }
    
            private static void bgw_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                
            }
    
            private static void bgw_DoWork(object sender, DoWorkEventArgs e)
            {
                Thread.Sleep(50000);
            }
        }
    }

    also find below the image for run time code:

    Please help. So that we can use this concept in multithreading.


    • Edited by Varsha11 Wednesday, April 5, 2017 7:18 AM
    Wednesday, April 5, 2017 7:11 AM

All replies

  • Disposing will not happen straight away but will happen soon after the object has been disposed
    Wednesday, April 5, 2017 7:21 AM
  • Hi Varsha11,

    Thread and Windows Services doesn't stops right away. It takes few seconds for them to dispose all the process as some them are still using. In the case of Windows Service the is a function called "Wait for Exit", which waits until the service stops and then move to next line.

    So you could use time to wait for some time before moving to next line, see if this can help you.


    Thanks,
    Sabah Shariq

    [If a post helps to resolve your issue, please click the "Mark as Answer" of that post or click Answered "Vote as helpful" button of that post. By marking a post as Answered or Helpful, you help others find the answer faster. ]

    Thursday, April 6, 2017 9:48 PM
    Moderator
  • 1. Dispose has nothing to do with the IsBusy. IsBusy will return true until the asynchronous operation has completed no matter did you or not dispose BackgroundWorker. The asynchronous work will run even if you dispose it and when work is completed will IsBusy be false and the instance can finally be cleared completely because its internal references to asynchronous work etc. has been completed. This is my view about how it works from using it and reviewing source code.

    2. Since BackgroundWorker is component its lifetime should be handled by its hosting container.

    3. Same as above the container of the component should be responsible for disposing BackgroundWorker it is hosting.

    To get around 2. and 3. I think you can clean up BackgroundWorker after it has completed its work in RunWorkerCompleted event, but I do not think that is great advice since the idea in components is that host manages them.

    Friday, April 7, 2017 9:21 AM
  • If your DoWorker method actually used the BWC then your app would crash with an ObjectDisposedException. You don't want to dispose of an object while it is in use. The correct approach to handling the cleanup of the BWC is to clean it up when it finishes which is what the complete event is for.

    Also, disposing has nothing to do with variable values. It simply releases the resources of the underlying object. So your check for whether ba is null will always be false. It'll get optimized away by the compiler in release mode.

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Linq;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    
    namespace ConsoleApp1
    {
        class Program
        {
            static void Main ( string[] args )
            {
                using (var bwc = new BackgroundWorker())
                {
                    bwc.DoWork += OnDoWork;
                    bwc.RunWorkerCompleted += OnWorkComplete;
    
                    //You set this but didn't actually use it...                
                    bwc.WorkerSupportsCancellation = true;
    
                    //Support progress notifications for fun
                    bwc.ProgressChanged += OnWorkProgress;
                    bwc.WorkerReportsProgress = true;
    
                    //Start the work
                    bwc.RunWorkerAsync();
    
                    //Handle Ctrl+C so user can terminate early
                    Console.CancelKeyPress += (o,e) => bwc.CancelAsync();
    
                    //Now wait
                    Console.WriteLine("Press Ctrl+C to terminate.");                
                    while (bwc.IsBusy)
                    {
                        //Yield the thread although I would generally prefer to use an event for this
                        Thread.Yield();
                    };
    
                    Console.WriteLine("Done waiting");
                };
            }
    
            static void OnDoWork ( object sender, DoWorkEventArgs e )
            {
                var bwc = sender as BackgroundWorker;
    
                //Doesn't matter what you do here
                for (var i = 0; i < 10; ++i)
                {
                    //Check for cancellation
                    if (bwc.CancellationPending)
                    {
                        bwc.ReportProgress(0, "Cancel requested");
                        e.Cancel = true;
                        return;
                    };
    
                    //Sleep a second
                    bwc.ReportProgress(0, $"Sleep {i}");
                    System.Threading.Thread.Sleep(1000);                
                };
            }
    
            static void OnWorkComplete ( object sender, RunWorkerCompletedEventArgs e )
            {
                //Do any post-work cleanup here but I wouldn't recommend disposing of the BWC as it is still
                //in use because it triggered this event      
                Console.WriteLine("BWC has completed");
            }        
    
            static void OnWorkProgress ( object sender, ProgressChangedEventArgs e )
            {
                Console.WriteLine(e.UserState);
            }
        }
    }
    

    Michael Taylor
    http://www.michaeltaylorp3.net

    Friday, April 7, 2017 2:09 PM
    Moderator