Dailycode.info

Short solution for short problems

Fire and event from a sub thread to the main thread in WPF

This small example shows you how to simply fire an event from a sub thread, capture it In the main thread and handle it in WPF.

The demo application (Attached to this post) simply starts a sub thread. In this thread we generate some random numbers and sent them back to the main thread. The main thread will show these numbers in a list.

First let’s investigate the main thread.

I’m using 2 private objects in my main thread:

private Dispatcher _uiDispatcher;

Thread _workerThread;

 

The _uiDispatcher will be used to store the main thread dispatcher in. The workerThread is the thread that will be used to handle the subroutine.

When I initiate the mainform, I will store the dispatcher of the main thread in the _uiDispatcher.

// Call from the main thread  

public void UseThisThreadForEvents()

{     

_uiDispatcher = Dispatcher.CurrentDispatcher;

} 

       

public MainWindow()

{

InitializeComponent();

       UseThisThreadForEvents();

}

 

So when the program starts, we have the dispatcher of the main thread that will be responsible to update the UI stored in a variable.

On the main form there is a button, when clicked it will start the sub thread.

private void button1_Click(object sender, RoutedEventArgs e)

{

    ThreadStart start;

    Worker worker = new Worker();

    worker.OnValueSent += new Worker.SentValueHandler(worker_OnValueSent);

    start = delegate()

    {

        worker.SentValuesEvery2Seconds();

    };

 

    // Create the thread and kick it started!

    _workerThread = new Thread(start);

    _workerThread.Priority = ThreadPriority.Lowest;

    _workerThread.Start();

           

}

 

In my worker class I declared an event that will be fired every 2 seconds. This event will be captured in the main thread and handled by the worker_OnValueSent method.

So here is where we will have to check in which thread we are and if needed invoke the dispatcher of the main thread so we can update the UI without invoking every control separately.

public delegate void OnValueSentDelegate(List<int> list);

 

void worker_OnValueSent(List<int> list)

{

    if (Dispatcher.CurrentDispatcher != _uiDispatcher)

    {

        _uiDispatcher.BeginInvoke(new OnValueSentDelegate(worker_OnValueSent), list);

 

    }

    else

    {

        listView1.Items.Add(list[0]);

        listView1.Items.Add(list[1]);

        listView1.Items.Add(list[2]);

    }

}

 

Simple logic written here. When the event is fired, we check if the dispatcher equals the _uiDispatcher (Dispatcher of the main thread). If not, we invoke the main thread dispatcher and use a delegate method to call the OnValueSent method.

So that’s how we do it.

For the people who need it, here the simple code of the worker class:

public class Worker

{

    public delegate void SentValueHandler(List<int> list);

 

    public event SentValueHandler OnValueSent;

 

    public void SentValuesEvery2Seconds()

    {

        int test = 0;

        while (test < 5)

        {

            Thread.Sleep(2000);

            if (OnValueSent != null)

            {

                Random rd = new Random();

 

                OnValueSent(new List<int>() { rd.Next(0, 1000), rd.Next(0, 1000), rd.Next(0, 1000) });

            }

            test++;

        }

    }

}

 

And here is a screenshot to give you an idea of what it does and how it looks.

 

 

WpfApplication1.zip (50.11 kb)