Execute a method in main thread from event handler
backgroundworker, c#, events, multithreading, winforms
Solution
You are enqueueing items on background thread (DoWork event handler runs on background thread), thus your event raised also in background thread.
Use `InvokeRequired` method to verify if you are on UI thread. And if not, then use `Invoke` to run code on UI thread:
private void QChanged(object sender, EventArgs e)
{
if (InvokeRequired)
{
Invoke((MethodInvoker)delegate { QChanged(sender, e); });
return;
}
// this code will run on main (UI) thread
DisplayThreadName();
}
Another option for you - use `ProgressChanged` event to enqueue items (don't forget to set `WorkerReportsProgress` to true). This event handler runs on UI thread:
private void bgwTest_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker worker = (BackgroundWorker)sender;
for (int i = 0; i < 11; i++)
{
// use user state for passing data
// which is not reflecting progress percentage
worker.ReportProgress(0, i);
System.Threading.Thread.Sleep(5000);
}
}
private void bgwTest_ProgressChanged(object sender, ProgressChangedEventArgs e)
{
string valueTExt = e.UserState.ToString();
qTest.Enqueue(valueTExt);
}
Problem
I have a custom Queue class inherited from Queue class. It has an event ItemAdded. In the event handler of this event i am executing a method. But it is running other than main thread, though i want it in main thread. I don't know how to do it. Any suggestion ? ``` //My custom class using System; using System.Collections; //Required to inherit non-generic Queue class. namespace QueueWithEvent { public class SmartQueue:Queue { public delegate void ItemAddedEventHandler(object sender, EventArgs e); public event ItemAddedEventHandler ItemAdded; protected virtual void OnItemAdded(EventArgs e) { if (ItemAdded != null) { ItemAdded(this, e); } } public override void Enqueue(object Item) { base.Enqueue(Item); OnItemAdded(EventArgs.Empty); } } } //Winform application using System; using System.ComponentModel; using System.Windows.Forms; using QueueWithEvent; namespace TestApp { public partial class Form1 : Form { SmartQueue qTest = new SmartQueue(); public Form1() { InitializeComponent(); qTest.ItemAdded += new SmartQueue.ItemAddedEventHandler(this.QChanged); } private void btnStartBgw_Click(object sender, EventArgs e) { DisplayThreadName(); bgwTest.RunWorkerAsync(); } private void bgwTest_DoWork(object sender, DoWorkEventArgs e) { try { for (int i = 0; i < 11; i++) { string valueTExt = i.ToString(); qTest.Enqueue(valueTExt); System.Threading.Thread.Sleep(5000); } } catch (Exception Ex) { MessageBox.Show(Ex.Message); } } private void DisplayThreadName() { string tName = System.Threading.Thread.CurrentThread.ManagedThreadId.ToString(); txtThreadName.Text = tName; } private void QChanged(object sender, EventArgs e) { //#########I want this method to run on main thread ############# DisplayThreadName(); } } } ``` Thanks in advance. SKPaul.