Invoking a method from the main thread, from a worker thread.

D

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
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.
 
J

Jianwei Sun

1. Define a delegate myDelegate.
2. define someMethod which matches the siganature of the myDelegate.
3. Call myDelegate.Invoke(someMethod).

Hello DaTurk,
 
P

Peter Duniho

DaTurk said:
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
 
J

Jon Skeet [C# MVP]

Jianwei Sun said:
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.
 
J

Jianwei Sun

Yes, you are right, I misunderstood his problem. sorry about that.
Hello Jon Skeet [C# MVP],
 
D

DaTurk

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();
}
}
}
}
 
J

Jon Skeet [C# MVP]

DaTurk said:
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".

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.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top