Search code examples
c#multithreadingthread-safetyinvokeautoresetevent

Application is not responding, when i tried to updated UI from another thread


Execution Flow:

  1. From main thread I invoked the new thread(Parallel thread), which is doing a long running process.
  2. Parallel thread is updating the main thread UI.
  3. I made my main thread to wait until parallel thread is complete.
  4. I need a synchronization between two thread.
  5. I need to use the result of parallel thread in main thread so I blocked main thread until parallel process complete.

Here is my code which is having issue, please give suggestion to resolve the issue.

    private readonly AutoResetEvent _resetEvent = new AutoResetEvent(false);
    private event EventHandler Workcompleted;

    private void button1_Click(object sender, EventArgs e)
    {
        Workcompleted += Completed;
        Thread thr = new Thread(UpdateUI);
        thr.Start("");

        _resetEvent.WaitOne();

         // Logical operation dependent on parallel process final result 

    }

    private void Completed(object sender, EventArgs args)
    {
        _resetEvent.Set();
    }

    private void UpdateUI(object txt)
    {
        for (int i = 0; i < 10; i++)
        {
            if (label1.InvokeRequired)
            {
                label1.Invoke(new ParameterizedThreadStart(UpdateUI), i.ToString());
            }
            else
            {
                label1.Text = (string)txt;
                Thread.Sleep(100);
            }
        }

        if (Workcompleted != null)
            Workcompleted(this, new EventArgs());

    }

Solution

  • It seems you are looking for a way to report progress in the UI during the course of the parallel operation and wait for the final result (synchronize) to do something with it.

    This could easily be accomplished using Async/Await, without having to run manual threads, synchronization constructs or thread marshaling (for UI invocation) and most importantly without blocking the UI thread.

    Here is an example of how to run a parallel operation, report progress back to the UI, update UI continuously and finally do something with the result when it is available.

    private async void button1_Click(object sender, EventArgs e)
    {
        var progress = new Progress<int>(ShowProgressInUi);
        var result = await Task.Run(() => DoParallelWorkAsync(progress));
    
        // Do something with final result
        label1.Text = result;
    }
    
    private void ShowProgressInUi(int progress)
    {
        label1.Text = string.Format("Progress: {0} % done...", progress);
    }
    
    private static async Task<string> DoParallelWorkAsync(IProgress<int> progress)
    {
        // This work is done in a separate thread.
        // In this case a background thread (from the thread pool),
        // but could be run on a foreground thread if the work is lengthy.
        for (var i = 1; i <= 10; i++)
        {
            // Simulate workload
            await Task.Delay(100);
            progress.Report(i * 10);
        }
    
        return "All done";
    }