Share via


How to fire event in UI thread

Question

Tuesday, November 1, 2016 8:57 AM

suppose i am working with thread like background worker. when long running operation will be completed then i want to raise event which will fire in UI thread. if i can fire event in UI thread then i can access win form controls from there and no cross thread related error will fire.

background worker has two event which fire in UI thread and those events are RunWorkerCompleted & ProgressChanged

please guide me with code sample that how to fire event in UI thread**.** thanks

All replies (5)

Wednesday, November 2, 2016 2:33 PM âś…Answered

i bg worker has some event which directly fire on UI thread. i am not interested to achieve this by using bg worker. i got one good link http://www.codeproject.com/Articles/31971/Understanding-SynchronizationContext-Part-I


Tuesday, November 1, 2016 2:54 PM

Refer to this full example on MSDN about how to use BackgroundWorker in combination with the events that you mentioned to accomplish what you want. Put breakpoints in each of the event handlers they define and then step through the code. It should answer any questions you may have. If you have further questions about this specific example then please respond here.


Wednesday, November 2, 2016 1:28 PM

i said when we are working with thread class then how could i fire event from a long running function which will fire in UI thread.

just curious to know this without using bg worker class.


Wednesday, November 2, 2016 1:44 PM

Mou_inn, 

Handle the events you mentioned on the UI thread.

Here is a complete example on how to do it. It is quite simple.

using System;
using System.ComponentModel;
using System.Windows.Forms;

namespace BackgroundWorkerSimple
{
    public partial class Form1 : Form
    {
        public Form1()
        {
            InitializeComponent();
            backgroundWorker1.WorkerReportsProgress = true;
            backgroundWorker1.WorkerSupportsCancellation = true;
        }

        private void startAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.IsBusy != true)
            {
                // Start the asynchronous operation.
                backgroundWorker1.RunWorkerAsync();
            }
        }

        private void cancelAsyncButton_Click(object sender, EventArgs e)
        {
            if (backgroundWorker1.WorkerSupportsCancellation == true)
            {
                // Cancel the asynchronous operation.
                backgroundWorker1.CancelAsync();
            }
        }

        // This event handler is where the time-consuming work is done.
        private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
        {
            BackgroundWorker worker = sender as BackgroundWorker;

            for (int i = 1; i <= 10; i++)
            {
                if (worker.CancellationPending == true)
                {
                    e.Cancel = true;
                    break;
                }
                else
                {
                    // Perform a time consuming operation and report progress.
                    System.Threading.Thread.Sleep(500);
                    worker.ReportProgress(i * 10);
                }
            }
        }

        // This event handler updates the progress.
        private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e)
        {
            resultLabel.Text = (e.ProgressPercentage.ToString() + "%");
        }

        // This event handler deals with the results of the background operation.
        private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
        {
            if (e.Cancelled == true)
            {
                resultLabel.Text = "Canceled!";
            }
            else if (e.Error != null)
            {
                resultLabel.Text = "Error: " + e.Error.Message;
            }
            else
            {
                resultLabel.Text = "Done!";
            }
        }
    }
}

You can see this and other examples on MSDN at BackgroundWorker Class

My Technet Articles

If you like this or another reply, vote it up!
If you think this or another reply answers the original question, mark it or propose it as an answer.

Mauricio Feijo
www.mauriciofeijo.com


Wednesday, November 2, 2016 2:47 PM

Why?  BWC eliminates the need for you to write the same exact code. If you don't want to use BWC then you should be looking into using await/async as defined here. This allows you to mix UI and non-UI work in the same method. But there are caveats that make it not the correct solution in some cases.

  • The method(s) in question must have implicit knowledge of the UI. For example if you want to update a progress bar in the UI then the method would have to do that directly which limits the ability to reuse the method.
  • The method using await/async would have to be called from the UI thread. For event handlers this is fine but for lower-level code in libraries there are no guarantees.
  • You can still deadlock the UI if you are not careful because you are updating the UI while it is in the middle of potentially blocking call.

The alternative solution is to define an interface that the caller (the UI) implements that you can call to notify of progress changes. .NET has a simple interface for this but you'll have to create your own for anything more complex. But this is basically what BWC does so if you are planning to go this route then reconsider using BWC instead.

The final solution that you can use is to use InvokeRequired and BeginInvoke on the control itself. But, like async/await, you are taking a hard dependency on the UI inside a method that likely shouldn't be worried about controls.

The best solution, to me, is to use BWC for generic worker methods and async/await for methods that are aware of the UI.