Reputation: 21
I am new to C# and am having trouble figuring out how to pass an event from a thread up to the GUI form thread. Any help would be appreciated. All of the examples I find are WAY too complicated. I just want to start with one event from the treat up to the GUI and have the GUI do something (right now, anything).
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; }
}
}
Upvotes: 1
Views: 2137
Reputation: 69372
Do you have to use this custom threading system, or are you able to use BackgroundWorkers? BackgroundWorkers
haven an event ProgressChanged
which fires on the thread that created the BackgroundWorker.
Alternatively, if you attach a handler to a background event from the UI thread, the work is still done on the background thread.
thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);
Therefore, you need to marshall the data to the UI thread. One way is by using 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
}));
}
Also, you can use if (myControl.InvokeRequired)
to check if you need to marshall data when changing a particular control.
if (this.InvokeRequired)
{
this.Invoke((Action)(() =>
{
//UI thread stuff
}
));
}
Edit to clarify
Your thread object that you've created needs to attach an event handler to the StuffHappenedDel
event. To do this, you use something like this
thread.StuffHappenedDel += new EventHandler<MessageEventArgs>(StuffHappenedDel);
before you call thread.Start()
. Now, this handler is called
private void StuffHappenedDel(Object seder, MessageEventArgs e)
{
j++;
}
whenever your event is fired.
If you want to make changes to any UI elements, you need to use the Invoke
method described above.
Upvotes: 1
Reputation: 6678
You need to register Form1 as a listener for the event. First, add a method like the following to Form1:
private void thread_SuffHappened(MessageEventArgs e)
{
MessageBox.Show("Stuff happened!");
}
And in Form1's constructor, register as a listener like so:
public Form1()
{
InitializeComponent();
thread = new workerThread();
thread.StuffHappened += new StuffHappenedDel(thread_StuffHappened);
thread.Start();
}
Upvotes: 1
Reputation: 27364
Look into the Background Worker Class. Also, you can always fire an event that is handled by your GUI Class (though not on the GUI Thread) and then call Invoke
Upvotes: 0