如何将单个事件从线程向上传递到GUI表单线程
本文关键字:GUI 单线程 表单 单个 事件 线程 | 更新日期: 2023-09-27 17:50:21
我是c#的新手,我很难弄清楚如何将事件从线程传递到GUI表单线程。任何帮助都会很感激。我找到的所有例子都太复杂了。我只想从从treat到GUI的一个事件开始,并让GUI做一些事情(现在,任何事情)。
namespace testEvents
{
public delegate void StuffHappenedDel( MessageEventArgs e);
public partial class Form1 : Form
{
workerThread thread;
int j = 0;
public Form1()
{
InitializeComponent();
thread = new workerThread();
thread.Start();
}
private void button1_Click(object sender, EventArgs e)
{
thread.Stop();
}
private void StuffHappenedDel(Object seder, EventArgs e)
{
j++;
}
}
public class workerThread
{
Thread worker;
private bool _quit = false;
/* I don't think this next line is correct*/
public event StuffHappenedDel StuffHappened;
protected virtual void OnStuffHappened(MessageEventArgs e)
{
if (StuffHappened != null)
StuffHappened( e);
}
public void Start()
{
ThreadStart start = new ThreadStart(Run);
worker = new Thread(start);
worker.Start();
}
private void Run()
{
int i = 0;
while (!_quit)
{
Thread.Sleep(1000);
i++;
OnStuffHappened(new MessageEventArgs(false, "it worked!"));
Console.WriteLine(string.Format("Slept {0} seconds.",i));
}
Console.WriteLine("Thread exiting");
}
}
public class MessageEventArgs : EventArgs
{
public MessageEventArgs(bool Error, string message)
{
IsError = Error;
Message = message;
}
public bool IsError { get; set; }
public string Message { get; set; }
}
}
您需要将Form1注册为事件的侦听器。首先,向Form1添加如下方法:
private void thread_SuffHappened(MessageEventArgs e)
{
MessageBox.Show("Stuff happened!");
}
在Form1的构造函数中,像这样注册为侦听器:
public Form1()
{
InitializeComponent();
thread = new workerThread();
thread.StuffHappened += new StuffHappenedDel(thread_StuffHappened);
thread.Start();
}
你是否必须使用这个自定义线程系统,或者你可以使用BackgroundWorkers?BackgroundWorkers
有一个事件ProgressChanged
,它在创建BackgroundWorker的线程上触发。
或者,如果你从UI线程附加一个处理程序到后台事件,工作仍然在后台线程上完成。
thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);
因此,您需要将数据编组到UI线程。一种方法是使用BeingInvoke
。
private void StuffHappenedDel(object sender, MessageEventArgs e)
{
this.myControl.BeginInvoke( new Action(
() =>
{
//UI thread work (likely anything that affects UI. Heavy
//processing can continue on the bg thread outside this code block
}));
}
另外,您可以使用if (myControl.InvokeRequired)
来检查在更改特定控件时是否需要编组数据。
if (this.InvokeRequired)
{
this.Invoke((Action)(() =>
{
//UI thread stuff
}
));
}
编辑澄清
您创建的线程对象需要将事件处理程序附加到StuffHappenedDel
事件。要做到这一点,您可以使用如下命令
thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);
在调用thread.Start()
之前。现在,这个处理程序叫做
private void StuffHappenedDel(Object seder, MessageEventArgs e)
{
j++;
}
当你的事件被触发时。
如果你想改变任何UI元素,你需要使用上面描述的Invoke
方法。
查看后台Worker类。此外,您还可以触发一个由GUI类处理的事件(尽管不在GUI线程上),然后调用Invoke