encapsulating invoking for thread communication

J

James Salter

Hi,

I have been using Control.Invoke() extensively on a project in order to
pass information from various worker threads to the interface thread.
Most of my worker objects hide this functionality by raising events that
are garuanteed to be fired in the constructing thread, by instantiating
a protected Control in the constructor and using it with Invoke later
on, to call delegates and then raise the events.

This is nice in the sense that it hides everything from the caller, and
is truly an encapsulated solution, but as I get more and more of these
worker threads I am starting to become concerned about the footprint of
these invisible Controls.

The alternatives to doing it this way are, get the caller to pass a
Control to the object (which might be inconvenient, and exposes the
internals somewhat), or maintain a static reference to the applications
main form somewhere. The latter solution is attractive, but i can't
figure out how to implement it without the client having to set the main
form themselves, which seems like a bad way of doing things.

What is the general convention for solving this problem?

James
 
D

Daniel Moth

You've already mentioned the conventional solution. Allow the user to
provide the control that you Invoke on. In fact, you should check that they
have provided a reference and if they have not you should let the event be
raised on the worker thread (it is their decision).

See the interface exposed by System.Timers.Timer [not available on the
Compact Framework, but the principle applies] and in particular the
SynchronizingObject property.

Finally, since the System.ComponentModel.ISynchronizeInvoke is not available
on netcf, you could define that to keep some compatibility with the full fx.

Cheers
Daniel
 
J

James Salter

Thanks, this is the sort of pattern I was looking for.

Using my own ISynchronizeInvoke definition might be a bit hazardous as
it would force clients of the object to subclass a control to implement
the interface, but they're likely passing the main form which is
subclassed already anyway. And passing an interface is a more attractive
solution to the problem than a concrete class.

Reading those docs also piqued my interest in ThreadPool, but I am not
entirely confident I understand its operation. If I call Sleep(100) from
within a ThreadPool invoked callback, my understanding is that the
pooled thread will block. This would then nullify any advantage of using
the pool. Is this correct?

James

Daniel said:
You've already mentioned the conventional solution. Allow the user to
provide the control that you Invoke on. In fact, you should check that
they have provided a reference and if they have not you should let the
event be raised on the worker thread (it is their decision).

See the interface exposed by System.Timers.Timer [not available on the
Compact Framework, but the principle applies] and in particular the
SynchronizingObject property.

Finally, since the System.ComponentModel.ISynchronizeInvoke is not
available on netcf, you could define that to keep some compatibility
with the full fx.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Hi,

I have been using Control.Invoke() extensively on a project in order
to pass information from various worker threads to the interface
thread. Most of my worker objects hide this functionality by raising
events that are garuanteed to be fired in the constructing thread, by
instantiating a protected Control in the constructor and using it with
Invoke later on, to call delegates and then raise the events.

This is nice in the sense that it hides everything from the caller,
and is truly an encapsulated solution, but as I get more and more of
these worker threads I am starting to become concerned about the
footprint of these invisible Controls.

The alternatives to doing it this way are, get the caller to pass a
Control to the object (which might be inconvenient, and exposes the
internals somewhat), or maintain a static reference to the
applications main form somewhere. The latter solution is attractive,
but i can't figure out how to implement it without the client having
to set the main form themselves, which seems like a bad way of doing
things.

What is the general convention for solving this problem?

James
 
D

Daniel Moth

Glad to have helped.
thread will block. This would then nullify any advantage of using the
pool. Is this correct?
Not exactly. Yes the threadpool should not be used for long blocking
operations as you are "taking out" one of the threadpool threads, but 100ms
doesn't seem long to me (in a managed environment). In addition, the pool
limit on netcf v1.0 is 256 so there are plenty more where it came from!

For more on the thread pool (compared to desktop and netcf v2.0) see this:
http://www.danielmoth.com/Blog/2005/02/threadpool.html

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


James Salter said:
Thanks, this is the sort of pattern I was looking for.

Using my own ISynchronizeInvoke definition might be a bit hazardous as it
would force clients of the object to subclass a control to implement the
interface, but they're likely passing the main form which is subclassed
already anyway. And passing an interface is a more attractive solution to
the problem than a concrete class.

Reading those docs also piqued my interest in ThreadPool, but I am not
entirely confident I understand its operation. If I call Sleep(100) from
within a ThreadPool invoked callback, my understanding is that the pooled
thread will block. This would then nullify any advantage of using the
pool. Is this correct?

James

Daniel said:
You've already mentioned the conventional solution. Allow the user to
provide the control that you Invoke on. In fact, you should check that
they have provided a reference and if they have not you should let the
event be raised on the worker thread (it is their decision).

See the interface exposed by System.Timers.Timer [not available on the
Compact Framework, but the principle applies] and in particular the
SynchronizingObject property.

Finally, since the System.ComponentModel.ISynchronizeInvoke is not
available on netcf, you could define that to keep some compatibility with
the full fx.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Hi,

I have been using Control.Invoke() extensively on a project in order to
pass information from various worker threads to the interface thread.
Most of my worker objects hide this functionality by raising events that
are garuanteed to be fired in the constructing thread, by instantiating
a protected Control in the constructor and using it with Invoke later
on, to call delegates and then raise the events.

This is nice in the sense that it hides everything from the caller, and
is truly an encapsulated solution, but as I get more and more of these
worker threads I am starting to become concerned about the footprint of
these invisible Controls.

The alternatives to doing it this way are, get the caller to pass a
Control to the object (which might be inconvenient, and exposes the
internals somewhat), or maintain a static reference to the applications
main form somewhere. The latter solution is attractive, but i can't
figure out how to implement it without the client having to set the main
form themselves, which seems like a bad way of doing things.

What is the general convention for solving this problem?

James
 
J

James Salter

I should have stated that i was going to have the thread spin in a loop
with the sleep(100) inside the loop.

I've since changed my strategy for that thread to using a timer for
updates, which is just more convenient overall, but some of my other
threads look like

while (!_close) { blocking IO operations; raise events;}

for a digital compass and gps. These then, would definitely take out a
thread.

Your blog advises that this isn't really so bad - there's plenty more
where they came from, which is as you say the main disadvantage.
However, I can't actually see a specific advantage in using the
threadpool in this situation, as I figure in the end the thread
allocation would look much the same as if I did it manually. Except my
thread startup time *might* be shorter.

Are my assumptions correct?

James

Daniel said:
Glad to have helped.
thread will block. This would then nullify any advantage of using the
pool. Is this correct?

Not exactly. Yes the threadpool should not be used for long blocking
operations as you are "taking out" one of the threadpool threads, but
100ms doesn't seem long to me (in a managed environment). In addition,
the pool limit on netcf v1.0 is 256 so there are plenty more where it
came from!

For more on the thread pool (compared to desktop and netcf v2.0) see this:
http://www.danielmoth.com/Blog/2005/02/threadpool.html

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Thanks, this is the sort of pattern I was looking for.

Using my own ISynchronizeInvoke definition might be a bit hazardous as it
would force clients of the object to subclass a control to implement the
interface, but they're likely passing the main form which is subclassed
already anyway. And passing an interface is a more attractive solution to
the problem than a concrete class.

Reading those docs also piqued my interest in ThreadPool, but I am not
entirely confident I understand its operation. If I call Sleep(100) from
within a ThreadPool invoked callback, my understanding is that the pooled
thread will block. This would then nullify any advantage of using the
pool. Is this correct?

James

Daniel said:
You've already mentioned the conventional solution. Allow the user to
provide the control that you Invoke on. In fact, you should check that
they have provided a reference and if they have not you should let the
event be raised on the worker thread (it is their decision).

See the interface exposed by System.Timers.Timer [not available on the
Compact Framework, but the principle applies] and in particular the
SynchronizingObject property.

Finally, since the System.ComponentModel.ISynchronizeInvoke is not
available on netcf, you could define that to keep some compatibility
with
the full fx.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/



Hi,

I have been using Control.Invoke() extensively on a project in order to
pass information from various worker threads to the interface thread.
Most of my worker objects hide this functionality by raising events
that
are garuanteed to be fired in the constructing thread, by instantiating
a protected Control in the constructor and using it with Invoke later
on, to call delegates and then raise the events.

This is nice in the sense that it hides everything from the caller, and
is truly an encapsulated solution, but as I get more and more of these
worker threads I am starting to become concerned about the footprint of
these invisible Controls.

The alternatives to doing it this way are, get the caller to pass a
Control to the object (which might be inconvenient, and exposes the
internals somewhat), or maintain a static reference to the applications
main form somewhere. The latter solution is attractive, but i can't
figure out how to implement it without the client having to set the
main
form themselves, which seems like a bad way of doing things.

What is the general convention for solving this problem?

James
 
D

Daniel Moth

Yes, if you need a thread dedicated for a single task (e.g. waiting on event
and then looping round) you should explicitly use a thread. Threadpool is
for short lived tasks and most commonly an easy fast way of going async.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


James Salter said:
I should have stated that i was going to have the thread spin in a loop
with the sleep(100) inside the loop.

I've since changed my strategy for that thread to using a timer for
updates, which is just more convenient overall, but some of my other
threads look like

while (!_close) { blocking IO operations; raise events;}

for a digital compass and gps. These then, would definitely take out a
thread.

Your blog advises that this isn't really so bad - there's plenty more
where they came from, which is as you say the main disadvantage. However,
I can't actually see a specific advantage in using the threadpool in this
situation, as I figure in the end the thread allocation would look much
the same as if I did it manually. Except my thread startup time *might* be
shorter.

Are my assumptions correct?

James

Daniel said:
Glad to have helped.
thread will block. This would then nullify any advantage of using the
pool. Is this correct?

Not exactly. Yes the threadpool should not be used for long blocking
operations as you are "taking out" one of the threadpool threads, but
100ms doesn't seem long to me (in a managed environment). In addition,
the pool limit on netcf v1.0 is 256 so there are plenty more where it
came from!

For more on the thread pool (compared to desktop and netcf v2.0) see
this:
http://www.danielmoth.com/Blog/2005/02/threadpool.html

Cheers
Daniel
--
http://www.danielmoth.com/Blog/


Thanks, this is the sort of pattern I was looking for.

Using my own ISynchronizeInvoke definition might be a bit hazardous as
it
would force clients of the object to subclass a control to implement the
interface, but they're likely passing the main form which is subclassed
already anyway. And passing an interface is a more attractive solution
to
the problem than a concrete class.

Reading those docs also piqued my interest in ThreadPool, but I am not
entirely confident I understand its operation. If I call Sleep(100) from
within a ThreadPool invoked callback, my understanding is that the
pooled
thread will block. This would then nullify any advantage of using the
pool. Is this correct?

James

Daniel Moth wrote:

You've already mentioned the conventional solution. Allow the user to
provide the control that you Invoke on. In fact, you should check that
they have provided a reference and if they have not you should let the
event be raised on the worker thread (it is their decision).

See the interface exposed by System.Timers.Timer [not available on the
Compact Framework, but the principle applies] and in particular the
SynchronizingObject property.

Finally, since the System.ComponentModel.ISynchronizeInvoke is not
available on netcf, you could define that to keep some compatibility
with
the full fx.

Cheers
Daniel
--
http://www.danielmoth.com/Blog/



Hi,

I have been using Control.Invoke() extensively on a project in order
to
pass information from various worker threads to the interface thread.
Most of my worker objects hide this functionality by raising events
that
are garuanteed to be fired in the constructing thread, by
instantiating
a protected Control in the constructor and using it with Invoke later
on, to call delegates and then raise the events.

This is nice in the sense that it hides everything from the caller,
and
is truly an encapsulated solution, but as I get more and more of these
worker threads I am starting to become concerned about the footprint
of
these invisible Controls.

The alternatives to doing it this way are, get the caller to pass a
Control to the object (which might be inconvenient, and exposes the
internals somewhat), or maintain a static reference to the
applications
main form somewhere. The latter solution is attractive, but i can't
figure out how to implement it without the client having to set the
main
form themselves, which seems like a bad way of doing things.

What is the general convention for solving this problem?

James
 

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