在事件处理程序的主线程中执行方法 [英] Execute a method in main thread from event handler
问题描述
我有一个自Queue类继承的自定义Queue类.它有一个事件ItemAdded.在此事件的事件处理程序中,我正在执行一个方法.但是它正在运行而不是主线程,尽管我希望它在主线程中.我不知道该怎么做.有什么建议吗?
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();
}
}
}
先谢谢了. 保罗.
推荐答案
您正在排队后台线程上的项目(DoWork事件处理程序在后台线程上运行),因此您的事件也在后台线程中引发.
You are enqueueing items on background thread (DoWork event handler runs on background thread), thus your event raised also in background thread.
使用InvokeRequired
方法来验证您是否在UI线程上.如果没有,请使用Invoke
在UI线程上运行代码:
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();
}
另一个适合您的选项-使用ProgressChanged
事件使项目入队(不要忘记将WorkerReportsProgress
设置为true).此事件处理程序在UI线程上运行:
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);
}
这篇关于在事件处理程序的主线程中执行方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!