By using this site, you agree to our updated Privacy Policy and our Terms of Use. Manage your Cookies Settings.
424,657 Members | 869 Online
Bytes IT Community
+ Ask a Question
Need help? Post your question and get tips & solutions from a community of 424,657 IT Pros & Developers. It's quick & easy.

Fire event in the same thread as the UI like BackgroundWorker

P: n/a
This is what I've always been wondered.
Suppose I've created a class named Agent, and the Agent does some
lengthy job. Of course I don't want to block the main window, so the
Agent does the job in a separate thread. If the job is progressed it
fires an event, and the main window handled the event by changing the
value of a progress bar. The problem is that this event is fired in
another thread so when the handler in the main window tries to access
the progress bar, an exception occurs. Until now, I've been solving
this problem by checking InvokeRequired and creating a delegate.

But the .NET 2.0's built-in BackgroundWorker seems to have solved this
with a very elegant way. When a BackgroundWorker fires the progress
event, it looks like the event is fired in the same thread as the main
window, because the InvalidOperationException does not occur when I
try to access UI controls in the handler. How could this be possible?
I want my Agent class to be able to the same thing. Making a lot of
delegations in the main window code makes the code dirty.

Please give me an idea. Thank you.

Oct 21 '07 #1
Share this Question
Share on Google+
4 Replies


P: n/a
Sin Jeong-hun wrote:
[...]
But the .NET 2.0's built-in BackgroundWorker seems to have solved this
with a very elegant way. When a BackgroundWorker fires the progress
event, it looks like the event is fired in the same thread as the main
window, because the InvalidOperationException does not occur when I
try to access UI controls in the handler. How could this be possible?
I want my Agent class to be able to the same thing. Making a lot of
delegations in the main window code makes the code dirty.

Please give me an idea. Thank you.
I don't know the specifics of how BackgroundWorker does it. Since it
doesn't require a specific Control instance given to it, I suspect it's
using AsyncOperation or something similar.

I'm pretty sure it raises events on the same thread that created the
BackgroundWorker when possible (though, if I recall correctly that's not
actually what it does in a console application...it does depend on
having a message pump), not specifically the main UI thread.

You could either use AsyncOperation yourself (you'd initialize it when
your object is created, and then use it to raise events on the same
thread used to create the object). Alternatively, if your object
depends on a specific Control instance, you may find it easier to just
use the Control instance to invoke a method to raise the event.

Pete
Oct 21 '07 #2

P: n/a
Yes, BackgroundWorker uses AsyncOperation to marshal the call back to the
correct thread. It doesn't use a particular control thread, it simply uses
the thread that was used to create the BackgroundWorker object.

--
Browse http://connect.microsoft.com/VisualStudio/feedback/ and vote.
http://www.peterRitchie.com/blog/
Microsoft MVP, Visual Developer - Visual C#
"Peter Duniho" wrote:
Sin Jeong-hun wrote:
[...]
But the .NET 2.0's built-in BackgroundWorker seems to have solved this
with a very elegant way. When a BackgroundWorker fires the progress
event, it looks like the event is fired in the same thread as the main
window, because the InvalidOperationException does not occur when I
try to access UI controls in the handler. How could this be possible?
I want my Agent class to be able to the same thing. Making a lot of
delegations in the main window code makes the code dirty.

Please give me an idea. Thank you.

I don't know the specifics of how BackgroundWorker does it. Since it
doesn't require a specific Control instance given to it, I suspect it's
using AsyncOperation or something similar.

I'm pretty sure it raises events on the same thread that created the
BackgroundWorker when possible (though, if I recall correctly that's not
actually what it does in a console application...it does depend on
having a message pump), not specifically the main UI thread.

You could either use AsyncOperation yourself (you'd initialize it when
your object is created, and then use it to raise events on the same
thread used to create the object). Alternatively, if your object
depends on a specific Control instance, you may find it easier to just
use the Control instance to invoke a method to raise the event.

Pete
Oct 22 '07 #3

P: n/a
Interesting. I hadn't seen the AsyncOperation class before. It's worth
noting that it is just a wrapper for the SynchronizationContext class
though. It is the particular current SynchronizationContext (available
via SynchronizationContext.Current) that does the actual work of
marshalling to the correct thread. If you're running Winforms, it'll
be a WindowsFormsSynchronizationContext. For WPF, it'll be a
DispatcherSynchronizationContext.

So AsyncOperation makes it easier to post progress and completion of
an operation to the UI (or "contextual") thread. Cool stuff.

Kent

Oct 22 '07 #4

P: n/a
On Oct 23, 1:00 am, "ken...@internode.on.net"
<ken...@internode.on.netwrote:
Interesting. I hadn't seen the AsyncOperation class before. It's worth
noting that it is just a wrapper for the SynchronizationContext class
though. It is the particular current SynchronizationContext (available
via SynchronizationContext.Current) that does the actual work of
marshalling to the correct thread. If you're running Winforms, it'll
be a WindowsFormsSynchronizationContext. For WPF, it'll be a
DispatcherSynchronizationContext.

So AsyncOperation makes it easier to post progress and completion of
an operation to the UI (or "contextual") thread. Cool stuff.

Kent
Right after I posted the original post, I thought maybe disassembling
the BackgroundWorker
would give me a hint. So I did it. It used several classes I'd never
seen before, and the logic
was quite unfamilar to me. But after all, I modified my class
according to the way BackgroundWoker
works, and now it works just like the BackgroundWorker. I don't need
to use InvokeRequired every time.
I think it would be worth for other people to try this.
Thank you for your replies, all.

Oct 25 '07 #5

This discussion thread is closed

Replies have been disabled for this discussion.