Search code examples
c#winformsprocessbackgroundworkerwait

How can I check if previously running ProgressChanged has finished in DoWork event in c#


Here is a scenario, its a winforms application where I have a collection of processes which i'm running one by one inside a for-loop in the DoWork event of Backgroundworker class. And I call ReportProgress() periodically in the for-loop to update UI.

Now when I call ReportProgress() it triggers ProgressChanged event where I have the code to update the UI with all the message I have set previously in DoWork. But as this runs in a separate thread, the control goes in parallel in DoWork, but I want to hold/wait the for-loop for sometime until the previously running ProgressChanged event.

Currently, I'm calling Thread.Sleep(1000) in for-loop before executing any operation in it (like picking up the next process and running it) and this code is giving me desired output. So I just wanted to check if there is any alternative solution where (I don't use Thread.Sleep instead) I can verify/ wait the for-loop until the previously running ProgressChanged event has finished its job, and only then I proceed to run the next process from the collection in for-loop.


Solution

  • Without addressing the issues with your overall design, the way you would do this is with a semaphore. The most basic example would be:

    static Semaphore _semaphore = new Semaphore(0,1);
    WorkStatus _workStatus;
    
    void DoWork()
    {
        _semaphore.WaitOne();
        try
        {
            _workStatus = Foo();  //Only one thread will be able to execute this at a time
        }
        finally
        {
            _semaphore.Release();
        }
    }
    
    void HandleProgressChanged()
    {
        _semaphore.WaitOne(); //Wait for any DoWork threads to finish
        try
        {
            DisplayProgress(_workStatus);
        }
        finally
        {
            _semaphore.Release();
        }
        Task.Run(DoWork);
    }