I know in a WinForm you can check if an Invoke is inquired and invoke
a method on the main thread. But can you do this in a class? Can I
call Invoke(someMethod) in my asynch event handler?
And if I can't do it this way, is there a way I can do it?
Thanks.
Jianwei Sun - 29 Aug 2007 23:59 GMT
1. Define a delegate myDelegate.
2. define someMethod which matches the siganature of the myDelegate.
3. Call myDelegate.Invoke(someMethod).
Hello DaTurk,
> I know in a WinForm you can check if an Invoke is inquired and invoke
> a method on the main thread. But can you do this in a class? Can I
[quoted text clipped - 3 lines]
>
> Thanks.
Jon Skeet [C# MVP] - 30 Aug 2007 07:27 GMT
> 1. Define a delegate myDelegate.
> 2. define someMethod which matches the siganature of the myDelegate.
> 3. Call myDelegate.Invoke(someMethod).
No, that will execute in the same thread. Delegate.Invoke doesn't have
any special threading behaviour, completely unlikely Control.Invoke.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Jianwei Sun - 30 Aug 2007 13:58 GMT
Yes, you are right, I misunderstood his problem. sorry about that.
Hello Jon Skeet [C# MVP],
>> 1. Define a delegate myDelegate.
>> 2. define someMethod which matches the siganature of the myDelegate.
>> 3. Call myDelegate.Invoke(someMethod).
> No, that will execute in the same thread. Delegate.Invoke doesn't have
> any special threading behaviour, completely unlikely Control.Invoke.
DaTurk - 30 Aug 2007 19:20 GMT
Ok..hmm..I don't grok..now I'm really confused..maybe an example would
help.
In the code below how would I get the callbackFromWorker() method to
execute on the thread named "MainThread". Right now when this program
runs it always reports that the callbackFromWorker() method is running
on the thread named "WorkerThread".
using System;
using System.Threading;
namespace ConsoleApplication1
{
class Program
{
static System.Threading.ThreadStart workerMethod;
static System.Threading.ThreadStart mainMethod;
static void Main(string[] args)
{
System.Threading.Thread.CurrentThread.Name = "MainThread";
workerMethod = new ThreadStart(doWork);
mainMethod = new ThreadStart(callbackFromWorker);
System.Threading.Thread workerThread = new
Thread(workerMethod);
workerThread.Name = "WorkerThread";
workerThread.Start();
Console.WriteLine("Press any key to exit");
Console.ReadLine();
}
static void callbackFromWorker()
{
Console.WriteLine("callbackFromWorker -> Running on: {0}",
System.Threading.Thread.CurrentThread.Name);
}
static void doWork()
{
while (true)
{
Console.WriteLine("doWork -> Running on: {0}",
System.Threading.Thread.CurrentThread.Name);
Thread.Sleep(3000);
mainMethod.Invoke();
}
}
}
}
Jon Skeet [C# MVP] - 30 Aug 2007 20:07 GMT
> Ok..hmm..I don't grok..now I'm really confused..maybe an example would
> help.
[quoted text clipped - 3 lines]
> runs it always reports that the callbackFromWorker() method is running
> on the thread named "WorkerThread".
Yes, it would - because Delegate.Invoke doesn't do anything fancy. It's
just the way of calling the delegate.
To get callbackFromWorker to run on the main thread, you'll need to
make the main thread effectively wait for work to do - that's what a UI
thread does. You can't hijack another thread and tell it to do
something when it's already busy doing something else.
Effectively, it sounds like you need a producer/consumer queue. See
http://pobox.com/~skeet/csharp/threads/deadlocks.shtml
(half way down) for an example queue. If your main thread is a consumer
and your worker thread is a producer, that should do the kind of thing
you want.

Signature
Jon Skeet - <skeet@pobox.com>
http://www.pobox.com/~skeet Blog: http://www.msmvps.com/jon.skeet
If replying to the group, please do not mail me too
Peter Duniho - 30 Aug 2007 00:57 GMT
> I know in a WinForm you can check if an Invoke is inquired and invoke
> a method on the main thread. But can you do this in a class? Can I
> call Invoke(someMethod) in my asynch event handler?
Can you elaborate on your question? You can call Control.Invoke() on
any method you like, whether that method exists in the Control-based
class or not. The delegate retains a reference to the instance used for
instance methods, so the context isn't important. It still gets called
regardless.
If you're asking whether there's a way to call some sort of "invoke"
method like Control.Invoke() but from a class that's not derived from a
Control, the short answer is "not easily".
The long answer is that to do something like this you need some sort of
context that defines where the delegate should run. The most obvious
way to do this is to have a queue of a class that includes a delegate
and parameters to pass to the delegate, and then consume that class in a
single thread. Other threads can add delegates and their parameters to
the queue, and then the consuming thread would dequeue them and execute
them.
That would ensure that the delegates get executed on the consuming thread.
When I first started doing .NET stuff, I played around a little with
some .NET class that, if I recall, help with this sort of thing outside
of the context of a Control-derived class. They are the AsyncOperation
and SynchronizationContext classes. It's been awhile and I don't recall
the specifics as to how I used them. But I do seem to recall that they
addressed an issue similar to what you're asking about.
Pete