best way to receive 'callbacks' in a GUI from other threads

E

emma_middlebrook

Hi

Advice needed about what's the best in the following situation.

In essence, I have a GUI that needs to detail time taken to do jobs
that execute in their own thread.

Currently, the GUI thread instantiates a class that wraps a job,
handing it a callback (delegate) to call once the job has finished. On
callback, always on a different thread than the GUI thread,
InvokeRequired is tested (and is always true), and the GUI is updated
via Invoke.

Is this standard and best? Or do people out there do something
different? I'm just concerned about the GUI class having to do a
thread-related test. It seems out of place: it shouldn't have to know
that other threads are involved so is there some kind of standard way
to hide this away?

Thanks and any help appreciated!

Emma.
 
A

Adam Clauss

Does this class (the thread) have a reference to the GUI form?
If yes, an alternative to invoking the DELEGATE from the thread, would be to
call Invoke/BeginInvoke directly on the form (passing the callback
delegate).

Ex:

class SomeClass
{
public void WorkerMethod()
{
//do whatever work necessary

mainForm.Invoke(callback);
}
}
 
P

Peter Duniho

[...]
Currently, the GUI thread instantiates a class that wraps a job,
handing it a callback (delegate) to call once the job has finished. On
callback, always on a different thread than the GUI thread,
InvokeRequired is tested (and is always true), and the GUI is updated
via Invoke.

Is this standard and best? Or do people out there do something
different? I'm just concerned about the GUI class having to do a
thread-related test. It seems out of place: it shouldn't have to know
that other threads are involved so is there some kind of standard way
to hide this away?

IMHO, I agree. There is also the issue that using Invoke causes the calling
thread to halt until the GUI thread processes it.

There is another solution, using the AsyncOperation class, that allows you
to specify a thread on which an operation will be done, queuing it to that
thread without blocking the current thread. The basic idea is that you
create the AsyncOperation on the thread on which you want the operation to
occur, and then you use the AsyncOperation on other threads to put the
operation on the desired thread.

I have used it as an alternative to the Invoke paradigm, and like it a lot.
The code looks simpler IMHO (I don't have a function that does two different
things depending on what thread it's on). It's probably a wash when you
compare things directly (you have an extra object to maintain with
AsyncOperation, and if you use it for raising an event you wind up with an
extra level of function calling), but it just seems cleaner to me, and I
like that the non-GUI thread can get on with what it's doing.

Anyway, none of this is to say that I actually think there's something wrong
with using Invoke. For example, in some cases you always know that you're
in a different thread. If that's true, then there's no reason to check
InvokeRequired. Just have two functions...one used by the non-GUI thread,
which invokes another function used by the GUI thread. It's just that
Invoke isn't the only way to address the issue and you may find some other
technique more to your liking.

Pete
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,



Is this standard and best? Or do people out there do something
different? I'm just concerned about the GUI class having to do a
thread-related test. It seems out of place: it shouldn't have to know
that other threads are involved so is there some kind of standard way
to hide this away?

Then do the opposite, let the worker thread have a reference to the UI
thread ( or to a control of the form to be exact) and is this thread the one
that invoke the "Finished" event. Note that Invoke receive a delegate, so
you can pass any info you need (like time taken executing) back to the UI
 
B

Brian Gideon

Emma,

If the mechanism you're using implies asynchronous behavior then I
would continue doing what you're doing. Most people assume that
callbacks are invoked from the thread running the asynchronous
operation. This is especially the case if you've used the
BeginSomeOperation/EndSomeOperation pattern.

Another option is to pass a reference a form or control to your worker
class and let it do the marshaling for you. Microsoft used a similar
pattern for the System.Timers.Timer object. In that case they created
a SynchronizingObject property that the Timer uses to automatically
marshal the Elapsed event. If SynchronizingObject is null then the
Elapsed event is executed on a ThreadPool thread. I find that to be a
rather elegant pattern especially if the worker class uses events to
report progress.

Brian
 

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