I got a worker thread which throws events, which are handled by common handler methods, Actually i want to achieve that the handler methods are executed by the thread who created the object containing the worker thread which throws the events.
I tried following code:
public partial class Form1 : Form
{
public event EventHandler Tested;
public Form1()
{
InitializeComponent();
Tested += new EventHandler(Form1_Tested);
}
private void Form1_Tested(object sender, EventArgs e)
{
Text = "Test";
}
private void Form1_Shown(object sender, EventArgs e)
{
#region Test 1
// Works normal in GUI-Thread directly
Form1_Tested(this, EventArgs.Empty);
#endregion
#region Test 2
// Works in worker thread and throws GUI exception
// because of foreign thread access
new Thread(new ThreadStart(delegate()
{
OnTested(EventArgs.Empty);
})).Start();
#endregion
#region Test 3
// Works in worker thread and returns to GUI-Thread
// to throw the event, so no need in eventhandler
// to use Control.Invoke();
AsyncOperation asyncOp = AsyncOperationManager.CreateOperation(null);
new Thread(new ThreadStart(delegate()
{
asyncOp.Post(new SendOrPostCallback(delegate(object obj)
{
OnTested(EventArgs.Empty);
}), null);
})).Start();
#endregion
}
protected virtual void OnTested(EventArgs e)
{
EventHandler tmpHandler = Tested;
if (tmpHandler != null)
tmpHandler(this, e);
}
}
I took a cloeser look at the Thread I using
Thread.CurrentThread.ManagedThreadId;
Before starting the worker thread, the id of my main thread is “1”. Within the UI Thread, just right before fireing the event, the Thread ID (of the worker thread) is “4”.
Now taking a closer look at the Thread Id in the handler method the Thread Id is something like “10” – but instead I expected the ID to be “1”.
I’m very confused about that.
Generally: Is my snippet the right way to do it, or what’s the best practice doing this (or even a working example)?
I wanted to avoid using Invoke on the worker thread actually.
Regards,
Thomas
Can you use a Task<> instead of a delegate? I think if you can, it might simplify things for you.
Basically, if you create a Task<>, you can access the result of that task by accessing the .Result property which will wait for the thread to finish and then either give you the return code or – if the thread threw an exception – will rethrow that exception in the context of the thread that is accessing the .Result property.
(If your thread doesn’t return anything, you can just call Task.Wait() instead of accessing .Result)
Some code might help to explain what I mean: