I need to implement in my class “Invoke()” method with the same behavior as Control.Invoke() has.
So when I am working with the instance of my InvokableEntity class from a thread different from thread where instance was created, I will be able to call invokableEntity.Invoke(delegate) and delegate will be executed in the context of the thread instance of InvokableEntity was created in.
And yes, I’ve read this question, it doesn’t helped me =(
Please take a look at his code, it illustrates my tries to implement described behavior for event handler (CustomProcessor_ProgressChanged method should be executed from thread where it was subscribed to the event, but I can’t do this):
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.ComponentModel;
using System.Windows.Forms;
namespace MultiThread
{
class Program
{
private static CustomProcessor customProcessor = new CustomProcessor();
static void Main(string[] args)
{
Console.WriteLine("Worker was run from thread: {0}", Thread.CurrentThread.ManagedThreadId);
customProcessor.ProgressChanged += new EventHandler(CustomProcessor_ProgressChanged);
Thread workerThread = new Thread(customProcessor.Process);
AsyncOperation asyncOperation = AsyncOperationManager.CreateOperation(null);
//SynchronizationContext context = SynchronizationContext.Current;
workerThread.Start(asyncOperation);
Console.ReadLine();
}
static void CustomProcessor_ProgressChanged(object sender, EventArgs e)
{
Console.WriteLine("Custom ProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId);
}
}
class CustomProcessor
{
public event EventHandler ProgressChanged;
public void RaiseProcessChanged(object o)
{
Console.WriteLine("RaiseProgressChanged was handled in thread: {0}", Thread.CurrentThread.ManagedThreadId);
if (this.ProgressChanged != null)
{
this.ProgressChanged(this, EventArgs.Empty);
}
}
public void Process(object asyncOperation)
{
Console.WriteLine("CustomProcessor.Process method was executed in thread: {0}", Thread.CurrentThread.ManagedThreadId);
AsyncOperation asyncOperationInternal = (AsyncOperation)asyncOperation;
asyncOperationInternal.Post(this.RaiseProcessChanged, null);
//SynchronizationContext context = (SynchronizationContext) asyncOperation;
//context.Send(s => this.RaiseProcessChanged(null), null);
//this.RaiseProcessChanged(new object());
}
}
}
Thanks!
Control.Invoke()uses thePostMessage()API call to post a message that will be consumed by the message pump of the main GUI thread.Let’s pretend that you create an instance of
CustomProcessorinThread#1that is not a GUI thread and after creating an instance ofCustomProcessor,Thread#1goes on with a long processing operation. If you need toInvokean operation onThread#1, you do not want to abort the current operation, it is a better idea instead to queue a workitem that will be consumed byThread#1each timeThread#1finishes a task.If there is no logic that enqueues new work from other threads and dequeues and processes it within
Thread#1, it will not magically work out-of-the-box.If you need this functionality on multiple threads that do not have a message pump, with a custom type that does not derive from
Control, a message queue or equivalent might be implemented. This way, however the creating thread will be spending its life in the message/work queue loop, most of the time waiting for new work – just like the main GUI thread in a Windows Forms application when you callApplication.Run(). This might not be what you want.