Which Async. Pattern should I be using?

  • Thread starter Thread starter Dog Ears
  • Start date Start date
D

Dog Ears

I've got a windows form that monitors the status of employees [location/work
status etc] it polls a database every 2 seconds to fetch updates [index on
history table with 'LastUpdate' Datetime field] then update a underlying
dataset bound to a grid using Invoke to marshal to the gui thread.

What pattern should I be using now I'm upgrading to .net 2.0? APM, async
delegates and BeginInvoke or Thread.Start etc...?

Should I be creating a single thread manulally (or using threadpool) and and
setting the polling on an internal loop with a Thread.Sleep(2000) ?

Any advice on what approach I should take would be very much appreciated.

Many thanks,
Graeme.
 
You could use a System.Timers.Timer which fires the Elasped event on a thread
pool thread. At the start of the event handler, stop the timer, then do the
work, the restart the timer.

You would still need to invoke to the UI thread as it fires on a pool thread.

HTH
 
Many thanks for your reply, just as I posted I stumbed across the timer
class (CLR via C#, J.Richter) it does seem a good option...

But my only concern is that most of the async code/logic etc is currently in
the form, i'd like to encapsulate it into the "monitoring" class, so that it
performs the asynchronous update 'internally' i'm just a bit concerned about
the updates. Maybe this would over complicate the design?

Regards,
Graeme.
 
If i have a collection that is being updated by another thread, and a Gui
control (grid) is bound to that collection, how do i update the collection
from the other thread, as the collection hasn't got an 'InvokeRequired'
property, do i just need to concentrate on Synchronisation and not worry
about 'invoke' to the gui thread?


Dog Ears said:
Many thanks for your reply, just as I posted I stumbed across the timer
class (CLR via C#, J.Richter) it does seem a good option...

But my only concern is that most of the async code/logic etc is currently
in the form, i'd like to encapsulate it into the "monitoring" class, so
that it performs the asynchronous update 'internally' i'm just a bit
concerned about the updates. Maybe this would over complicate the design?

Regards,
Graeme.
 
Dog said:
If i have a collection that is being updated by another thread, and a Gui
control (grid) is bound to that collection, how do i update the collection
from the other thread, as the collection hasn't got an 'InvokeRequired'
property, do i just need to concentrate on Synchronisation and not worry
about 'invoke' to the gui thread?

Yes. Invoke is required for things that involve window messages, but
for other data objects not connected to those, you just need ordinary
synchronization.

That said, sometimes using Invoke or BeginInvoke is one of the simplest
ways to synchronize other data objects. You'd have to have some Control
instance that the data object is tied to (either because it's an actual
member of the Control instance, or because of some design
characteristic), so that you can use that Control's Invoke or
BeginInvoke method. But other than that, it can be a useful technique.

Pete
 
This is not completely true. If the collection class implements any of
the notification mechanisms that data binding supports (the
<property>Changed event pattern, implementation of the
INotifyCollectionChanged or INotifyPropertyChanged interfaces), then you
have to make sure that you make changes to your collection on the UI thread,
so that whatever is bound to it won't throw an exception when the
notification event from the collection triggers a UI change.

I'm assuming here, of course, that your "yes" answer is in response to
the question about concentrating solely on synchronization, and not on
calling Invoke.
 
Nicholas said:
This is not completely true. If the collection class implements any of
the notification mechanisms that data binding supports (the
<property>Changed event pattern, implementation of the
INotifyCollectionChanged or INotifyPropertyChanged interfaces), then you
have to make sure that you make changes to your collection on the UI thread,
so that whatever is bound to it won't throw an exception when the
notification event from the collection triggers a UI change.

Thank you for the clarification.

My answer does of course assume that one is interacting with the
collection class itself only. I agree that if you have somehow
connected the connection class to a UI control, that the thread issues
are introduced.

But IMHO those aren't a characteristic of the collection itself; that
has more to do with what's bound to the property of the collection. You
could just as easily have the property bound to something without such a
requirement AFAIK. For example, simply subscribing to a
<property>Changed event doesn't require Invoke; it's only when the event
handler itself winds up doing something with a Control that that would
come up.

I assume the same sort of thing is true for the INotify... interfaces,
but I'm not that familiar with them so I won't make a claim regarding those.

IMHO, the key here is understanding how one is actually using the
collection, and handling cross-thread UI issues via Invoke if
appropriate. A collection class in and of itself has no such issues.

Pete
 
I agree, I was just pointing it out since "Dog Ears" specifically stated
that his collection was bound to a GUI control.
 
Nicholas said:
I agree, I was just pointing it out since "Dog Ears" specifically stated
that his collection was bound to a GUI control.

Ah, yes. Somehow I managed to overlook that, in spite of it being
mentioned more than once.

So, I guess my suggestion that using Invoke or BeginInvoke is useful for
synchronization is more than just something that might be useful for
convenience. It might actually be the best way to solve the
synchronization issues, just as you suggest. :)

Pete
 
so in a collection object that asynchronously updates itself internally, how
would I would i update the collection (from within) and marshal the calls
across to the gui thread?
 
The collection itself would be updated based on the async calls that come
in.

The collection would then raise events ("User Added", "User Offline") on
either the IOCP thread the async call came in on, or on the system
threadpool. Whoever handles the event (aka: The GUI) would need to do the
control.invoke to get off the IOCP thread, and back to the GUI thread.

This means the collection would need to be thread safe, and the GUI would
need to know that any events it receives from the collection need to be
marshalled prior to doing anything fun with.

Alternativly, you could take the approach of the collection having a control
property on it, that is set by the GUI. When an async callback happens, the
list updates itself, marshalls over to the right thread (using the
control.BeginInvoke), then raises the event.
 
The problem is the events are standard binding interface events like
INotifyPropertyChanged.PropertyChanged, and the events are handled by
standard control, wich isn't going to be checking the InvokeRequired, i
guess the simple answer is do all the async stuff from the form?

Regards,
Graeme.

Chris Mullins said:
The collection itself would be updated based on the async calls that come
in.

The collection would then raise events ("User Added", "User Offline") on
either the IOCP thread the async call came in on, or on the system
threadpool. Whoever handles the event (aka: The GUI) would need to do the
control.invoke to get off the IOCP thread, and back to the GUI thread.

This means the collection would need to be thread safe, and the GUI would
need to know that any events it receives from the collection need to be
marshalled prior to doing anything fun with.

Alternativly, you could take the approach of the collection having a
control property on it, that is set by the GUI. When an async callback
happens, the list updates itself, marshalls over to the right thread
(using the control.BeginInvoke), then raises the event.

--
Chris Mullins


Dog Ears said:
so in a collection object that asynchronously updates itself internally,
how would I would i update the collection (from within) and marshal the
calls across to the gui thread?

Peter Duniho said:
Nicholas Paldino [.NET/C# MVP] wrote:
I agree, I was just pointing it out since "Dog Ears" specifically
stated that his collection was bound to a GUI control.

Ah, yes. Somehow I managed to overlook that, in spite of it being
mentioned more than once.

So, I guess my suggestion that using Invoke or BeginInvoke is useful for
synchronization is more than just something that might be useful for
convenience. It might actually be the best way to solve the
synchronization issues, just as you suggest. :)

Pete
 
Dog said:
The problem is the events are standard binding interface events like
INotifyPropertyChanged.PropertyChanged, and the events are handled by
standard control, wich isn't going to be checking the InvokeRequired, i
guess the simple answer is do all the async stuff from the form?

Well, IMHO the simplest means is to do what I suggested originally.
That, make sure you've got a Control that is associated in some specific
way with the collection and use that Control's Invoke for handling
synchronization.

The way it would work is that whatever asynchronously would update the
collection, would instead use Invoke or BeginInvoke to call a method on
the Control that "owns" the collection to actually do the update on the
collection. That method will execute on the correct thread, and as long
as you only use this mechanism for updating the collection it will
_also_ have the effect of synchronizing access to the collection, since
only that one thread will ever actually modify the collection.

If you don't have a Control that naturally correlates on a one-to-one
basis with the collection, then an alternative is to use an
AsyncOperation, which can also be tied to a specific thread (including
the main GUI thread where everything else is happening). I don't recall
the details, as it's been a year or so since I was playing with it. But
it's an alternative that I know worked for me at the time.

Pete
 
Well, IMHO the simplest means is to do what I suggested originally.
That, make sure you've got a Control that is associated in some specific
way with the collection and use that Control's Invoke for handling
synchronization.

I'm confused, if i want to creat the class to handle it's own async fetching
from the DB how can i link it to a Control? should i inherit from Control
and then before doing updates to the collection check for InvokeRequired,
isn't there a way to do this without requireing the Control as a base
classs?
The way it would work is that whatever asynchronously would update the
collection, would instead use Invoke or BeginInvoke to call a method on
the Control that "owns" the collection to actually do the update on the
collection. That method will execute on the correct thread, and as long
as you only use this mechanism for updating the collection it will _also_
have the effect of synchronizing access to the collection, since only that
one thread will ever actually modify the collection.

If you don't have a Control that naturally correlates on a one-to-one
basis with the collection, then an alternative is to use an
AsyncOperation, which can also be tied to a specific thread (including the
main GUI thread where everything else is happening). I don't recall the
details, as it's been a year or so since I was playing with it. But it's
an alternative that I know worked for me at the time.

Is this AsyncOperation used in the "Event Based Async Pattern" mentioned in
the MSDN docs? I've implemented a working prototype of this and it seems to
be working.

Cheers Pete, i'll keep chipping away. thankyou.
Graeme.
 
Dog said:
I'm confused, if i want to creat the class to handle it's own async fetching
from the DB how can i link it to a Control? should i inherit from Control
and then before doing updates to the collection check for InvokeRequired,
isn't there a way to do this without requireing the Control as a base
classs?

Yes. I don't mean you need to inherit Control for the async class. I
just mean that you need to logically connect the Control to the
collection somehow. This could be as simple as saying "well, I've got
this form that's always around and I can invoke an anonymous method
using the form instance to make sure my code is executed on that form's
thread", or you could actually have a form that either owns the data
structure or is itself part of the data structure somehow (though that
last example is probably not what you want...I'm just saying it _could_
be in other situations).

The point is simply that for Control.Invoke or BeginInvoke to be useful,
you need to have some instance of a Control somewhere that makes sense
to use when calling Invoke or BeginInvoke. For that to work, that
instance needs to have some sort of logical, architectural relationship
to the collection. The relationship could be very casual, but it does
need to be reliable so that anytime you need to invoke code on that
control's thread, the control is there to use.
Is this AsyncOperation used in the "Event Based Async Pattern" mentioned in
the MSDN docs? I've implemented a working prototype of this and it seems to
be working.

Well, you're not very specific about the documentation page you're
looking at. But surely it's the same class; I'm only aware of one
AsyncOperation class in .NET.

It seems to me that if you have no control instance that lends itself
naturally to the relationship I'm talking about above, and especially if
you already have some code using AsyncOperation that correctly invokes
code on a specific thread, then that's probably the way to go. :)

Pete
 
Peter,
I think I'm getting there, the msdn docs I mentioned are here:

http://msdn2.microsoft.com/en-us/library/hkasytyf.aspx

The walkthrough creates a component that raises events, I've hacked my
collection to implement the pattern but the progress events are raised every
two seconds to itself via the AsynOperation.Post, this (I think) means they
are handled on the correct thread [well no errors are thrown, and does now
it 2.0 am I right?] the changed instance objects are "marshalled" [is that
the correct expression] to the correct thread as parameters and the
collection is updated in the correct thread and IBindingList changed events
are raised as normal. so all seems to work as intended.

I also took a look at the BackgroundWorker class that seems to have similar
properties, it also uses a similar pattern internally [courtesy of
reflector] using the AsyncOperation that you mentioned before.

Many thanks for your pointers, it's good to bounce ideas around.

thankyou,
Graeme.

N.B Peter, do you never sleep?
 
Back
Top