我是C#的新手,并且无法弄清楚如何将事件从线程传递到GUI表单线程。任何帮助,将不胜感激。我发现的所有例子都太复杂了。我只想从处理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; }
}
}
答案 0 :(得分:1)
您是否必须使用此自定义线程系统,或者您是否可以使用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
方法。
答案 1 :(得分:1)
您需要将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();
}
答案 2 :(得分:0)
查看Background Worker Class。此外,您始终可以触发由GUI类处理的事件(尽管不在GUI线程上),然后调用Invoke