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

Time Critical Process in .NET

P: n/a
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker thread
raises an event that is handled by the UI thread, to update a rich text
control with details of the completed operation. I am using a rich text box
so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal the
operation to the correct thread, and so as not to hold up the worker thread,
but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this type
of application, but does anyone have any ideas about how I could make my
application more deterministic? I am not certain what is going on in these
2.5 seconds, so it might be useful if I could find out, but I am not sure
how I would do that.

TIA

Charles
Jul 21 '05 #1
Share this Question
Share on Google+
77 Replies


P: n/a
Charles,

You get my almost standard answer (however a little bit more, so don't
direct stop reading).

When one thread depends from another thread than you can not use
multithreading (Or you should use optimistic multiprocessing however than we
come in a complete other area).

However when you are able to bring the dependend process to the
workerthread, than you have fulfiled again on this condition.

Cor
Jul 21 '05 #2

P: n/a
Hi Cor

I thought that I was removing the dependency by using BeginInvoke.

I need the critical process to be performed on a separate thread so that the
UI remains responsive, and of course I cannot update the screen on the
worker thread for the usual reason.

I was wondering if there was a way of making essential parts of my process
not interruptible, so that I know that they will always execute in one go,
without being switched out of context. Also, is there a way of stopping the
GC from doing its thing at key times, as I fear this may also be causing
arbitrary delays?

Charles
"Cor Ligthert" <no************@planet.nl> wrote in message
news:uC**************@TK2MSFTNGP15.phx.gbl...
Charles,

You get my almost standard answer (however a little bit more, so don't
direct stop reading).

When one thread depends from another thread than you can not use
multithreading (Or you should use optimistic multiprocessing however than
we come in a complete other area).

However when you are able to bring the dependend process to the
workerthread, than you have fulfiled again on this condition.

Cor

Jul 21 '05 #3

P: n/a
"Cor Ligthert" <no************@planet.nl> wrote in
news:uC**************@TK2MSFTNGP15.phx.gbl...
Charles,

You get my almost standard answer (however a little bit more, so don't
direct stop reading).

When one thread depends from another thread than you can not use
multithreading (Or you should use optimistic multiprocessing however than
we come in a complete other area).


No!!! Doing lengthy calculations in a background thread and displaying the
results in a GUI thread is an absolutely common multithreading situation.
Almost any serious multithreading task I can think of involves some kind of
inter-thread communication/synchronization.

To the OP: You'll never be able to guarantee an upper limit of your
execution time, but that's mainly due to HD swapping, buggy drivers or
non-cooperative realtime processes. If none of that happens, your best bet
is to find out *what* happens. (But you already knew that).

It's hard to give you any better advices without more details about your
app, but I'd try the following:
- Print out the current time (using some high-res-timer) at some strategic
points to find out exactly *what* takes those 2.5 sec. Is it always the same
step in your background-thread operation? Is it the communication between
the threads?
- Monitor the .NET performance counters. Is there maybe some correlation to
GC collection or some other runtime event?
- Which GC do you use?
- 2.5 s is quite long, maybe you can interrupt your process in a debugger
while it happens?
- Can you remove/simplify parts of your application (like using some fake
calculation instead of the real one, or using a simple text box), to see if
the problem still happens?

Hope one of these helps...

Niki
Jul 21 '05 #4

P: n/a
Hi Charles,

Upping the priority of your worker thread to Time Critical may be
appropriate for what you want to accomplish, as it would theoretically stop
other threads from interrupting its progress. However, I suspect this would
leave you with an unresponsive GUI (which you want to avoid) as well as a
potentially unstable process.

Does this behaviour occur whilst running the process in its fully compiled
Release Mode, ie compiled without Debug symbols and run directly, not via
VS.NET? I've noticed that applications run within VS (even in Release Mode)
often hang for a few seconds if an exception is thrown, even if this
exception is handled by the CLR or your app. Bear in mind that some
routines throw exceptions as a matter of course such as IsDate or IsNumeric,
both of which try to cast a variable to their respective data-types and
return false if an exception is caught, albeit internally.

Cheers,
Alex Clark

"Charles Law" <bl***@nowhere.com> wrote in message
news:uu***************@TK2MSFTNGP12.phx.gbl...
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread raises an event that is handled by the UI thread, to update a rich
text control with details of the completed operation. I am using a rich
text box so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the operation to the correct thread, and so as not to hold up the worker
thread, but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type of application, but does anyone have any ideas about how I could make
my application more deterministic? I am not certain what is going on in
these 2.5 seconds, so it might be useful if I could find out, but I am not
sure how I would do that.

TIA

Charles

Jul 21 '05 #5

P: n/a
Hi Alex

Thanks for the response. I have set the priority to Above Normal, but, as
you suggest, don't wish to raise it any further.
Does this behaviour occur whilst running the process in its fully compiled
Release Mode, ie compiled without Debug symbols and run directly, not via
VS.NET?
Yes, it does. I am running it on a laptop (Celeron processor), and I was
also wondering if the fact that it has an LCD screen means that screen
updates take longer. That said, I can also run the whole thing in debug on
another laptop (3.0 GHz P4) and not get these problems.

Charles
"Alex Clark" <qu*******@community.nospam> wrote in message
news:eE**************@TK2MSFTNGP09.phx.gbl... Hi Charles,

Upping the priority of your worker thread to Time Critical may be
appropriate for what you want to accomplish, as it would theoretically
stop other threads from interrupting its progress. However, I suspect
this would leave you with an unresponsive GUI (which you want to avoid) as
well as a potentially unstable process.

Does this behaviour occur whilst running the process in its fully compiled
Release Mode, ie compiled without Debug symbols and run directly, not via
VS.NET? I've noticed that applications run within VS (even in Release
Mode) often hang for a few seconds if an exception is thrown, even if this
exception is handled by the CLR or your app. Bear in mind that some
routines throw exceptions as a matter of course such as IsDate or
IsNumeric, both of which try to cast a variable to their respective
data-types and return false if an exception is caught, albeit internally.

Cheers,
Alex Clark

"Charles Law" <bl***@nowhere.com> wrote in message
news:uu***************@TK2MSFTNGP12.phx.gbl...
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in
a specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread raises an event that is handled by the UI thread, to update a rich
text control with details of the completed operation. I am using a rich
text box so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in
my process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is
every chance that it completes in a realistic time, and all is well. If I
stop outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the operation to the correct thread, and so as not to hold up the worker
thread, but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type of application, but does anyone have any ideas about how I could
make my application more deterministic? I am not certain what is going on
in these 2.5 seconds, so it might be useful if I could find out, but I am
not sure how I would do that.

TIA

Charles


Jul 21 '05 #6

P: n/a
Hi Niki

Thanks for the response. I currently display the absolute and elapsed times
using a high res timer, which is how I can see the difference between the
expected and actual timings. I guess I could add more time displays, but it
would generate a lot of output, and whilst it might tell me when and where
in my code the excess time is taken, I am not sure it will necessarily tell
me why. I don't think it is my code (they all say that), because it is so
random.
- Monitor the .NET performance counters. Is there maybe some correlation
to GC collection or some other runtime event?
How can I tell when garbage collection occurs?
- Which GC do you use?
How many are there? I thought there was just the one, built-in to the
framework.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:uN**************@tk2msftngp13.phx.gbl... "Cor Ligthert" <no************@planet.nl> wrote in
news:uC**************@TK2MSFTNGP15.phx.gbl...
Charles,

You get my almost standard answer (however a little bit more, so don't
direct stop reading).

When one thread depends from another thread than you can not use
multithreading (Or you should use optimistic multiprocessing however than
we come in a complete other area).


No!!! Doing lengthy calculations in a background thread and displaying the
results in a GUI thread is an absolutely common multithreading situation.
Almost any serious multithreading task I can think of involves some kind
of inter-thread communication/synchronization.

To the OP: You'll never be able to guarantee an upper limit of your
execution time, but that's mainly due to HD swapping, buggy drivers or
non-cooperative realtime processes. If none of that happens, your best bet
is to find out *what* happens. (But you already knew that).

It's hard to give you any better advices without more details about your
app, but I'd try the following:
- Print out the current time (using some high-res-timer) at some strategic
points to find out exactly *what* takes those 2.5 sec. Is it always the
same step in your background-thread operation? Is it the communication
between the threads?
- Monitor the .NET performance counters. Is there maybe some correlation
to GC collection or some other runtime event?
- Which GC do you use?
- 2.5 s is quite long, maybe you can interrupt your process in a debugger
while it happens?
- Can you remove/simplify parts of your application (like using some fake
calculation instead of the real one, or using a simple text box), to see
if the problem still happens?

Hope one of these helps...

Niki

Jul 21 '05 #7

P: n/a
Hi,

As you imagine, there may be "other things" affecting your timing. Notebook
computer power saving modes are notorious for causing unpredictable
behavior(s) of this sort. Make sure that you have configured those to 'high
power" or whatever setting might be equivalent -- and see if the problem
persists.

I have a Toshiba notebook, configured to "never hibernate," and to stay in
full-power mode all the time, except when on battery However... It does
enter power saving mode, which screws things up. If I were to guess, I'd
say that you might be seeing a similar problem.

Is there any possibility that there is some other application or service on
your test system that may be causing some sort substantial delay?

Dick

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.
Jul 21 '05 #8

P: n/a
Charles,
This sounds like the ideal use of multiple threads!

I'm not sure what Cor was smoking when he responded :-|

However due to the nature of .NET (non-deterministic garbage collection) &
Windows preemptive scheduling; "real-time" critical processes are hard to
achieve.

Can you use CLR profiler or custom performance counters to identify that a
Garbage Collection is not occurring during this "critical" process? Can you
redesign the critical process to minimize garbage collections if this is the
problem?

Are you certain that windows did not suspend your program in favor of
allowing another program to run?

Have you tried using Thread.Priority and/or Process.PriorityClass &
Process.PriorityBoostEnabled so Windows will favor your thread/process?

WARNING: I would use Process.PriorityClass & Process.PriorityBoostEnabled
with extreme caution!

Info on the CLR Profiler:
http://msdn.microsoft.com/library/de...nethowto13.asp

http://msdn.microsoft.com/library/de...anagedapps.asp

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:uu***************@TK2MSFTNGP12.phx.gbl...
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread raises an event that is handled by the UI thread, to update a rich
text control with details of the completed operation. I am using a rich
text box so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the operation to the correct thread, and so as not to hold up the worker
thread, but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type of application, but does anyone have any ideas about how I could make
my application more deterministic? I am not certain what is going on in
these 2.5 seconds, so it might be useful if I could find out, but I am not
sure how I would do that.

TIA

Charles

Jul 21 '05 #9

P: n/a
Jay

Something as this.
http://reports-archive.adm.cs.cmu.ed...-CS-05-118.pdf

I just took it from Google, I saw that a little bit is written in it what I
mean, although this is about a database is this always when the main thread
*needs* its information earlier than that the worker thread can give it.

Whatever reason there is for that.

This is a multiprocessor approach however in my opinion is the
multithreading approach not different from that in my opinion.

Cor
Jul 21 '05 #10

P: n/a
Hi Dick

I had a look at the system tray, and disabled Norton Antivirus Auto-protect,
and initially thought that I had sorted the problem, but on a long run I saw
the problem again.

You make a good point, though, about hibernation and power saving, since,
eventually, this laptop will be left unattended for half an hour whilst it
does its thing, and it would muck everything up if it went to sleep in the
middle of the show.

The laptop in question is an out-of-the-box Dell, with nothing much
installed apart from the framework and my application. I will have a closer
look though, just in case.

Thanks.

Charles
"Dick Grier" <di**************@msn.com> wrote in message
news:e0**************@tk2msftngp13.phx.gbl...
Hi,

As you imagine, there may be "other things" affecting your timing.
Notebook computer power saving modes are notorious for causing
unpredictable behavior(s) of this sort. Make sure that you have
configured those to 'high power" or whatever setting might be
equivalent -- and see if the problem persists.

I have a Toshiba notebook, configured to "never hibernate," and to stay in
full-power mode all the time, except when on battery However... It does
enter power saving mode, which screws things up. If I were to guess, I'd
say that you might be seeing a similar problem.

Is there any possibility that there is some other application or service
on your test system that may be causing some sort substantial delay?

Dick

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.

Jul 21 '05 #11

P: n/a
CMM
1) Run the application in release mode. Applications with debug symbol
baggage tend to run slower.
2) Boost the priority of the thread.
3) I'm not sure if this is redundant with #2 but you can try increasing the
application's priority. Via Task Manager, select the process and select "Set
Priority." I'm sure there's a way to do this via the framework or at least a
Win32 API as well.
4) Make sure the slowdown isn't caused by exceptions (even if handled in
your worker thread). Exceptions will halt the thread as the framework
processes it.
5) Similarly to #3... be aware that some methods may throw and handle their
own exceptions... all transparent to the caller. This will still slow
everything down even though you never get the exception. You might be able to
find the offending method by going to Debug|Exceptions and setting ALL
exceptions to 'Break into Debugger' regardless if the exception is handled.

In the end, after all is said and done, it might be due to garbage
collection. Garbage collection will pause your app momentarily. There are
tricks to minimize this and effective object management and pooling helps
(are you instantiating and releasing a lot of non-value type objects?).
"Charles Law" wrote:
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker thread
raises an event that is handled by the UI thread, to update a rich text
control with details of the completed operation. I am using a rich text box
so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal the
operation to the correct thread, and so as not to hold up the worker thread,
but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this type
of application, but does anyone have any ideas about how I could make my
application more deterministic? I am not certain what is going on in these
2.5 seconds, so it might be useful if I could find out, but I am not sure
how I would do that.

TIA

Charles

Jul 21 '05 #12

P: n/a
Cor,

That paper describes an effort to parallelize one specific database
transaction using thread level speculation (TLS) techniques. TLS is a
mechanism for getting the most out of dual-core processors. TLS would
most likely be implemented by a compiler or JIT engine. The paper has
little useful information for the OP. However, it is interesting.

Brian

Cor Ligthert wrote:
Jay

Something as this.
http://reports-archive.adm.cs.cmu.ed...-CS-05-118.pdf

I just took it from Google, I saw that a little bit is written in it
what I mean, although this is about a database is this always when
the main thread *needs* its information earlier than that the worker
thread can give it.

Whatever reason there is for that.

This is a multiprocessor approach however in my opinion is the
multithreading approach not different from that in my opinion.

Cor


Jul 21 '05 #13

P: n/a
Hi,

Screen savers can be a problem, too. Some notebooks have a "built-in" one
that acts like Windows -- a little.

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.
Jul 21 '05 #14

P: n/a
"Charles Law" <bl***@nowhere.com> wrote in
news:up**************@TK2MSFTNGP10.phx.gbl...
Hi Niki

Thanks for the response. I currently display the absolute and elapsed
times using a high res timer, which is how I can see the difference
between the expected and actual timings. I guess I could add more time
displays, but it would generate a lot of output, and whilst it might tell
me when and where in my code the excess time is taken, I am not sure it
will necessarily tell me why. I don't think it is my code (they all say
that), because it is so random.


Is it really random? How can you know without knowing where it happens? I
thought all you knew was that it doesn't happen every time?

Did you analyze the time delta's? How are they distributed? Is there a
normal distribution around 300 ms plus some peaks at 2,5 s? If so, did you
check where those peaks are? (I always dump output like that to a text file
and use Excel to analyze it later)
- Monitor the .NET performance counters. Is there maybe some correlation
to GC collection or some other runtime event?


How can I tell when garbage collection occurs?


I have a German windows version, so I can't tell you the exact name of the
performance counter, should be something like "Number of GCs" in the ".NET
Memory" performance counters section. It increases by one with each GC
collection. Use perfmon to record it while you test your app.
- Which GC do you use?


How many are there? I thought there was just the one, built-in to the
framework.


MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll) and
Server (mscorsvr.dll). When running in Workstation mode, latency is more of
a concern than space or efficiency. A server with multiple processors and
clients connected over a network can afford some latency, but throughput is
now a top priority. Rather than shoehorn both of these scenarios into a
single GC scheme, Microsoft has included two garbage collectors that are
tailored to each situation."
[http://msdn.microsoft.com/library/de...perftechs.asp]

You'll have to host the runtime to choose between the two, but I think the
workstation version is the better choice for you anyway.

Niki
Jul 21 '05 #15

P: n/a
Indeed. In this case, though, the screen saver has been set to none, and I
have observed the entire process and nothing obvious interrupts it.

Charles
"Dick Grier" <di**************@msn.com> wrote in message
news:e7*************@TK2MSFTNGP12.phx.gbl...
Hi,

Screen savers can be a problem, too. Some notebooks have a "built-in" one
that acts like Windows -- a little.

--
Richard Grier (Microsoft Visual Basic MVP)

See www.hardandsoftware.net for contact information.

Author of Visual Basic Programmer's Guide to Serial Communications, 4th
Edition ISBN 1-890422-28-2 (391 pages) published July 2004. See
www.mabry.com/vbpgser4 to order.

Jul 21 '05 #16

P: n/a
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds. Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than 25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
"Charles Law" <bl***@nowhere.com> wrote in
news:up**************@TK2MSFTNGP10.phx.gbl...
Hi Niki

Thanks for the response. I currently display the absolute and elapsed
times using a high res timer, which is how I can see the difference
between the expected and actual timings. I guess I could add more time
displays, but it would generate a lot of output, and whilst it might tell
me when and where in my code the excess time is taken, I am not sure it
will necessarily tell me why. I don't think it is my code (they all say
that), because it is so random.


Is it really random? How can you know without knowing where it happens? I
thought all you knew was that it doesn't happen every time?

Did you analyze the time delta's? How are they distributed? Is there a
normal distribution around 300 ms plus some peaks at 2,5 s? If so, did you
check where those peaks are? (I always dump output like that to a text
file and use Excel to analyze it later)
- Monitor the .NET performance counters. Is there maybe some correlation
to GC collection or some other runtime event?


How can I tell when garbage collection occurs?


I have a German windows version, so I can't tell you the exact name of the
performance counter, should be something like "Number of GCs" in the ".NET
Memory" performance counters section. It increases by one with each GC
collection. Use perfmon to record it while you test your app.
- Which GC do you use?


How many are there? I thought there was just the one, built-in to the
framework.


MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll) and
Server (mscorsvr.dll). When running in Workstation mode, latency is more
of a concern than space or efficiency. A server with multiple processors
and clients connected over a network can afford some latency, but
throughput is now a top priority. Rather than shoehorn both of these
scenarios into a single GC scheme, Microsoft has included two garbage
collectors that are tailored to each situation."
[http://msdn.microsoft.com/library/de...perftechs.asp]

You'll have to host the runtime to choose between the two, but I think the
workstation version is the better choice for you anyway.

Niki

Jul 21 '05 #17

P: n/a
> 1) Run the application in release mode. Applications with debug symbol
baggage tend to run slower.
It is currently running that way.
2) Boost the priority of the thread.
Currently set to AboveNormal.
3) I'm not sure if this is redundant with #2 but you can try increasing
the
application's priority. Via Task Manager, select the process and select
"Set
Priority." I'm sure there's a way to do this via the framework or at least
a
Win32 API as well.
Not tried, but I am inclined to agree with you assessment.
4) Make sure the slowdown isn't caused by exceptions (even if handled in
your worker thread). Exceptions will halt the thread as the framework
processes it.
Each task in the process is in a Try .. Catch block, and any exception would
appear on screen. In this case I do not get any exception reported.
5) Similarly to #3... be aware that some methods may throw and handle
their
own exceptions... all transparent to the caller. This will still slow
everything down even though you never get the exception. You might be able
to
find the offending method by going to Debug|Exceptions and setting ALL
exceptions to 'Break into Debugger' regardless if the exception is
handled.
The data in these tasks are pretty constant, so I would expect the
exceptions to be constant too, if there are any. The extra time does not
always appear in the same place (or at all), but the data do not change.

In the end, after all is said and done, it might be due to garbage
collection. Garbage collection will pause your app momentarily. There are
tricks to minimize this and effective object management and pooling helps
(are you instantiating and releasing a lot of non-value type objects?).
This is certainly one of my concerns, but I am unsure how I can restrict
garbage collection to non-time sensitive areas of my code. And yes, I am
creating a lot of non-value types; mostly associated with the raising of
events.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F3**********************************@microsof t.com... 1) Run the application in release mode. Applications with debug symbol
baggage tend to run slower.
2) Boost the priority of the thread.
3) I'm not sure if this is redundant with #2 but you can try increasing
the
application's priority. Via Task Manager, select the process and select
"Set
Priority." I'm sure there's a way to do this via the framework or at least
a
Win32 API as well.
4) Make sure the slowdown isn't caused by exceptions (even if handled in
your worker thread). Exceptions will halt the thread as the framework
processes it.
5) Similarly to #3... be aware that some methods may throw and handle
their
own exceptions... all transparent to the caller. This will still slow
everything down even though you never get the exception. You might be able
to
find the offending method by going to Debug|Exceptions and setting ALL
exceptions to 'Break into Debugger' regardless if the exception is
handled.

In the end, after all is said and done, it might be due to garbage
collection. Garbage collection will pause your app momentarily. There are
tricks to minimize this and effective object management and pooling helps
(are you instantiating and releasing a lot of non-value type objects?).
"Charles Law" wrote:
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in
a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread
raises an event that is handled by the UI thread, to update a rich text
control with details of the completed operation. I am using a rich text
box
so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in
my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is
every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the
operation to the correct thread, and so as not to hold up the worker
thread,
but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type
of application, but does anyone have any ideas about how I could make my
application more deterministic? I am not certain what is going on in
these
2.5 seconds, so it might be useful if I could find out, but I am not sure
how I would do that.

TIA

Charles

Jul 21 '05 #18

P: n/a
Hi Jay

A lot of good information, as usual. I shall mull it over and try some of
this out.
Can you use CLR profiler or custom performance counters to identify that a
Garbage Collection is not occurring during this "critical" process? Can
you redesign the critical process to minimize garbage collections if this
is the problem?
Is it possible to suspend garbage collection for critical sections?
Are you certain that windows did not suspend your program in favor of
allowing another program to run?
There is nothing obviously getting control; very little else is running. The
m/c is not networked, and apart from Norton Antivirus - which is disabled -
there is nothing much else.
Have you tried using Thread.Priority and/or Process.PriorityClass &
Process.PriorityBoostEnabled so Windows will favor your thread/process?
I haven't, but I will take a look.

Cheers.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl... Charles,
This sounds like the ideal use of multiple threads!

I'm not sure what Cor was smoking when he responded :-|

However due to the nature of .NET (non-deterministic garbage collection) &
Windows preemptive scheduling; "real-time" critical processes are hard to
achieve.

Can you use CLR profiler or custom performance counters to identify that a
Garbage Collection is not occurring during this "critical" process? Can
you redesign the critical process to minimize garbage collections if this
is the problem?

Are you certain that windows did not suspend your program in favor of
allowing another program to run?

Have you tried using Thread.Priority and/or Process.PriorityClass &
Process.PriorityBoostEnabled so Windows will favor your thread/process?

WARNING: I would use Process.PriorityClass & Process.PriorityBoostEnabled
with extreme caution!

Info on the CLR Profiler:
http://msdn.microsoft.com/library/de...nethowto13.asp

http://msdn.microsoft.com/library/de...anagedapps.asp

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:uu***************@TK2MSFTNGP12.phx.gbl...
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in
a specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread raises an event that is handled by the UI thread, to update a rich
text control with details of the completed operation. I am using a rich
text box so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in
my process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is
every chance that it completes in a realistic time, and all is well. If I
stop outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the operation to the correct thread, and so as not to hold up the worker
thread, but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type of application, but does anyone have any ideas about how I could
make my application more deterministic? I am not certain what is going on
in these 2.5 seconds, so it might be useful if I could find out, but I am
not sure how I would do that.

TIA

Charles


Jul 21 '05 #19

P: n/a
CMM
1) Force a garbage collection when it won't interfere with your time
sensitive loop... using gc.Collect().
2) Use structures. These get allocated and deallocated on demand.
3) Reuse objects where possible rather than reinstantiating new ones.
Perhaps using some sort of object pool or something.

Hopefully someone here might have some more robust "hardcore" ways to help.
The following article might help too...
-
http://msdn.microsoft.com/library/de...etgcbasics.asp
- http://msdn.microsoft.com/msdnmag/is...2/default.aspx

"Charles Law" wrote:
1) Run the application in release mode. Applications with debug symbol
baggage tend to run slower.


It is currently running that way.
2) Boost the priority of the thread.


Currently set to AboveNormal.
3) I'm not sure if this is redundant with #2 but you can try increasing
the
application's priority. Via Task Manager, select the process and select
"Set
Priority." I'm sure there's a way to do this via the framework or at least
a
Win32 API as well.


Not tried, but I am inclined to agree with you assessment.
4) Make sure the slowdown isn't caused by exceptions (even if handled in
your worker thread). Exceptions will halt the thread as the framework
processes it.


Each task in the process is in a Try .. Catch block, and any exception would
appear on screen. In this case I do not get any exception reported.
5) Similarly to #3... be aware that some methods may throw and handle
their
own exceptions... all transparent to the caller. This will still slow
everything down even though you never get the exception. You might be able
to
find the offending method by going to Debug|Exceptions and setting ALL
exceptions to 'Break into Debugger' regardless if the exception is
handled.


The data in these tasks are pretty constant, so I would expect the
exceptions to be constant too, if there are any. The extra time does not
always appear in the same place (or at all), but the data do not change.

In the end, after all is said and done, it might be due to garbage
collection. Garbage collection will pause your app momentarily. There are
tricks to minimize this and effective object management and pooling helps
(are you instantiating and releasing a lot of non-value type objects?).


This is certainly one of my concerns, but I am unsure how I can restrict
garbage collection to non-time sensitive areas of my code. And yes, I am
creating a lot of non-value types; mostly associated with the raising of
events.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F3**********************************@microsof t.com...
1) Run the application in release mode. Applications with debug symbol
baggage tend to run slower.
2) Boost the priority of the thread.
3) I'm not sure if this is redundant with #2 but you can try increasing
the
application's priority. Via Task Manager, select the process and select
"Set
Priority." I'm sure there's a way to do this via the framework or at least
a
Win32 API as well.
4) Make sure the slowdown isn't caused by exceptions (even if handled in
your worker thread). Exceptions will halt the thread as the framework
processes it.
5) Similarly to #3... be aware that some methods may throw and handle
their
own exceptions... all transparent to the caller. This will still slow
everything down even though you never get the exception. You might be able
to
find the offending method by going to Debug|Exceptions and setting ALL
exceptions to 'Break into Debugger' regardless if the exception is
handled.

In the end, after all is said and done, it might be due to garbage
collection. Garbage collection will pause your app momentarily. There are
tricks to minimize this and effective object management and pooling helps
(are you instantiating and releasing a lot of non-value type objects?).
"Charles Law" wrote:
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in
a
specific time frame. The time when the process starts is not especially
important, but it must be complete within a small number of seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread
raises an event that is handled by the UI thread, to update a rich text
control with details of the completed operation. I am using a rich text
box
so that when a failure occurs I can colour the message red.

The problem I have is that sometimes, for no apparent reason, a step in
my
process takes an inordinate amount of time, e.g 2.5 seconds instead of
perhaps 300 ms. When this happens, the complete process overruns my time
frame, and it has to be repeated. When I repeat the process there is
every
chance that it completes in a realistic time, and all is well. If I stop
outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the
operation to the correct thread, and so as not to hold up the worker
thread,
but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type
of application, but does anyone have any ideas about how I could make my
application more deterministic? I am not certain what is going on in
these
2.5 seconds, so it might be useful if I could find out, but I am not sure
how I would do that.

TIA

Charles


Jul 21 '05 #20

P: n/a
CMM
If the culprit is the events perhaps you should rethink your design... and
use a shared or global variable to communicate state. The UI thread would
periodically check the status rather then the worker thread informing the UI
via events.

"Charles Law" wrote:
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds. Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than 25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
"Charles Law" <bl***@nowhere.com> wrote in
news:up**************@TK2MSFTNGP10.phx.gbl...
Hi Niki

Thanks for the response. I currently display the absolute and elapsed
times using a high res timer, which is how I can see the difference
between the expected and actual timings. I guess I could add more time
displays, but it would generate a lot of output, and whilst it might tell
me when and where in my code the excess time is taken, I am not sure it
will necessarily tell me why. I don't think it is my code (they all say
that), because it is so random.


Is it really random? How can you know without knowing where it happens? I
thought all you knew was that it doesn't happen every time?

Did you analyze the time delta's? How are they distributed? Is there a
normal distribution around 300 ms plus some peaks at 2,5 s? If so, did you
check where those peaks are? (I always dump output like that to a text
file and use Excel to analyze it later)
- Monitor the .NET performance counters. Is there maybe some correlation
to GC collection or some other runtime event?

How can I tell when garbage collection occurs?


I have a German windows version, so I can't tell you the exact name of the
performance counter, should be something like "Number of GCs" in the ".NET
Memory" performance counters section. It increases by one with each GC
collection. Use perfmon to record it while you test your app.
- Which GC do you use?

How many are there? I thought there was just the one, built-in to the
framework.


MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll) and
Server (mscorsvr.dll). When running in Workstation mode, latency is more
of a concern than space or efficiency. A server with multiple processors
and clients connected over a network can afford some latency, but
throughput is now a top priority. Rather than shoehorn both of these
scenarios into a single GC scheme, Microsoft has included two garbage
collectors that are tailored to each situation."
[http://msdn.microsoft.com/library/de...perftechs.asp]

You'll have to host the runtime to choose between the two, but I think the
workstation version is the better choice for you anyway.

Niki


Jul 21 '05 #21

P: n/a
The status is accumulated in the rich text box, so just checking it
periodically would mean that some state changes could be missed. The rich
text box needs to keep a history of all states, as notified by the worker
thread.

One thought I had was to accumulate the state in-memory, which would
undoubtedly be quicker than updating the screen all the time. The problem I
can see with that is that I don't have an in-memory class that can interpret
rtf codes, such as the ones that are embedded in the rich text control to
show failed processes in red.

Do you know of a class that can process/manipulate rtf w/o rendering it?

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
If the culprit is the events perhaps you should rethink your design... and
use a shared or global variable to communicate state. The UI thread would
periodically check the status rather then the worker thread informing the
UI
via events.

"Charles Law" wrote:
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds.
Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less
than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed
time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than
25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I
am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears
to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from
the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute
time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
> "Charles Law" <bl***@nowhere.com> wrote in
> news:up**************@TK2MSFTNGP10.phx.gbl...
>> Hi Niki
>>
>> Thanks for the response. I currently display the absolute and elapsed
>> times using a high res timer, which is how I can see the difference
>> between the expected and actual timings. I guess I could add more time
>> displays, but it would generate a lot of output, and whilst it might
>> tell
>> me when and where in my code the excess time is taken, I am not sure
>> it
>> will necessarily tell me why. I don't think it is my code (they all
>> say
>> that), because it is so random.
>
> Is it really random? How can you know without knowing where it happens?
> I
> thought all you knew was that it doesn't happen every time?
>
> Did you analyze the time delta's? How are they distributed? Is there a
> normal distribution around 300 ms plus some peaks at 2,5 s? If so, did
> you
> check where those peaks are? (I always dump output like that to a text
> file and use Excel to analyze it later)
>
>>> - Monitor the .NET performance counters. Is there maybe some
>>> correlation
>>> to GC collection or some other runtime event?
>>
>> How can I tell when garbage collection occurs?
>
> I have a German windows version, so I can't tell you the exact name of
> the
> performance counter, should be something like "Number of GCs" in the
> ".NET
> Memory" performance counters section. It increases by one with each GC
> collection. Use perfmon to record it while you test your app.
>
>>> - Which GC do you use?
>>
>> How many are there? I thought there was just the one, built-in to the
>> framework.
>
> MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll)
> and
> Server (mscorsvr.dll). When running in Workstation mode, latency is
> more
> of a concern than space or efficiency. A server with multiple
> processors
> and clients connected over a network can afford some latency, but
> throughput is now a top priority. Rather than shoehorn both of these
> scenarios into a single GC scheme, Microsoft has included two garbage
> collectors that are tailored to each situation."
> [http://msdn.microsoft.com/library/de...perftechs.asp]
>
> You'll have to host the runtime to choose between the two, but I think
> the
> workstation version is the better choice for you anyway.
>
> Niki
>


Jul 21 '05 #22

P: n/a
There are certainly points in my process where I could perform a garbage
collect w/o upsetting the timing, so I will try a gc.Collect there and see
what happens.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C3**********************************@microsof t.com...
1) Force a garbage collection when it won't interfere with your time
sensitive loop... using gc.Collect().
2) Use structures. These get allocated and deallocated on demand.
3) Reuse objects where possible rather than reinstantiating new ones.
Perhaps using some sort of object pool or something.

Hopefully someone here might have some more robust "hardcore" ways to
help.
The following article might help too...
-
http://msdn.microsoft.com/library/de...etgcbasics.asp
- http://msdn.microsoft.com/msdnmag/is...2/default.aspx

"Charles Law" wrote:
> 1) Run the application in release mode. Applications with debug symbol
> baggage tend to run slower.


It is currently running that way.
> 2) Boost the priority of the thread.


Currently set to AboveNormal.
> 3) I'm not sure if this is redundant with #2 but you can try increasing
> the
> application's priority. Via Task Manager, select the process and select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.


Not tried, but I am inclined to agree with you assessment.
> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.


Each task in the process is in a Try .. Catch block, and any exception
would
appear on screen. In this case I do not get any exception reported.
> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.


The data in these tasks are pretty constant, so I would expect the
exceptions to be constant too, if there are any. The extra time does not
always appear in the same place (or at all), but the data do not change.
>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type objects?).


This is certainly one of my concerns, but I am unsure how I can restrict
garbage collection to non-time sensitive areas of my code. And yes, I am
creating a lot of non-value types; mostly associated with the raising of
events.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F3**********************************@microsof t.com...
> 1) Run the application in release mode. Applications with debug symbol
> baggage tend to run slower.
> 2) Boost the priority of the thread.
> 3) I'm not sure if this is redundant with #2 but you can try increasing
> the
> application's priority. Via Task Manager, select the process and select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.
> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.
> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.
>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type objects?).
>
>
> "Charles Law" wrote:
>
>> Hi guys
>>
>> I have a time critical process, running on a worker thread. By "time
>> critical", I mean that certain parts of the process must be completed
>> in
>> a
>> specific time frame. The time when the process starts is not
>> especially
>> important, but it must be complete within a small number of seconds.
>>
>> The operations I am performing do not take a long time (hundreds of
>> milliseconds), but as each part of the process is complete, my worker
>> thread
>> raises an event that is handled by the UI thread, to update a rich
>> text
>> control with details of the completed operation. I am using a rich
>> text
>> box
>> so that when a failure occurs I can colour the message red.
>>
>> The problem I have is that sometimes, for no apparent reason, a step
>> in
>> my
>> process takes an inordinate amount of time, e.g 2.5 seconds instead of
>> perhaps 300 ms. When this happens, the complete process overruns my
>> time
>> frame, and it has to be repeated. When I repeat the process there is
>> every
>> chance that it completes in a realistic time, and all is well. If I
>> stop
>> outputting to the screen, I do not get the problem.
>>
>> When updating the screen on the UI thread, I use BeginInvoke, to
>> marshal
>> the
>> operation to the correct thread, and so as not to hold up the worker
>> thread,
>> but this does not seem to help.
>>
>> I realise that Windows (XP in this case) is not the ideal o/s for this
>> type
>> of application, but does anyone have any ideas about how I could make
>> my
>> application more deterministic? I am not certain what is going on in
>> these
>> 2.5 seconds, so it might be useful if I could find out, but I am not
>> sure
>> how I would do that.
>>
>> TIA
>>
>> Charles
>>
>>
>>


Jul 21 '05 #23

P: n/a
Charles,

Did you ever saw that queue sample (using multithreading) that I once have
sent to this newsgroup. Maybe can that be a solution because it can maybe
make your problem easier to handle. This is because I have the idea that I
read some things in your messages in this thread what can be solved with
this.

http://groups-beta.google.com/group/...629fad6b6eb48a

This is real "a sample without any production value", in the thread is as
well another sample with a more realistic approach.

Cor
Jul 21 '05 #24

P: n/a
Charles,

I did not look all solutions you got, however for me looks some as putting
the horse behind the car.

By instance that looking for the garbage collecting or screensaver (in my
opinion wild guesses) will cost time, and that will in my opinion only make
your problem worse. I can add a virusscanner, from which I have seen, can
have a terrible influence on a laptop, and there are a lot of those.

In my opinion do you have to fix the problem inside your solution and not
outside, that never will lead to results. It can happen again, when a kind
of change in the system configuration is happening, that you did not expect.

Just my thought,

Cor
Jul 21 '05 #25

P: n/a
Hi Cor

I have just looked at it now. I will have a think about how it could help
me.

Thanks.

Charles
"Cor Ligthert" <no************@planet.nl> wrote in message
news:%2***************@TK2MSFTNGP15.phx.gbl...
Charles,

Did you ever saw that queue sample (using multithreading) that I once have
sent to this newsgroup. Maybe can that be a solution because it can maybe
make your problem easier to handle. This is because I have the idea that
I read some things in your messages in this thread what can be solved with
this.

http://groups-beta.google.com/group/...629fad6b6eb48a

This is real "a sample without any production value", in the thread is as
well another sample with a more realistic approach.

Cor

Jul 21 '05 #26

P: n/a
Cor

I agree with you that I need to fix the problem within my programme.
However, as you say, things like virus checkers can have an adverse effect
on performance, so I will also have to specify that virus checking must be
disabled. This laptop lives in a secure lab environment, and will only ever
be used for this process, so it is not unreasonable to expect that it will
never be the subject of a virus attack.

Charles
"Cor Ligthert" <no************@planet.nl> wrote in message
news:uL**************@TK2MSFTNGP14.phx.gbl...
Charles,

I did not look all solutions you got, however for me looks some as putting
the horse behind the car.

By instance that looking for the garbage collecting or screensaver (in my
opinion wild guesses) will cost time, and that will in my opinion only
make your problem worse. I can add a virusscanner, from which I have seen,
can have a terrible influence on a laptop, and there are a lot of those.

In my opinion do you have to fix the problem inside your solution and not
outside, that never will lead to results. It can happen again, when a kind
of change in the system configuration is happening, that you did not
expect.

Just my thought,

Cor

Jul 21 '05 #27

P: n/a
CMM
The worker thread can push "states" into a stack collection. The UI thread
can pop states out. You'd use the SyncLock mechanism (VB parlance) to allow
for both threads to access the collection. The UI thread would NOT enumerate
the collection and fill the rich text box at the same time (which might be an
expensive process)... that's dumb... rather it would pop out the states and
collect them itself and then fill the textbox on its own time so as to leave
the stack collection alone as quickly as possible.

Your RTF thing confused me... is the worker thread sending back RTF strings?
Why? And if so, why can't you just store those same strings in a regular ol'
collection?

Just an idea.

"Charles Law" wrote:
The status is accumulated in the rich text box, so just checking it
periodically would mean that some state changes could be missed. The rich
text box needs to keep a history of all states, as notified by the worker
thread.

One thought I had was to accumulate the state in-memory, which would
undoubtedly be quicker than updating the screen all the time. The problem I
can see with that is that I don't have an in-memory class that can interpret
rtf codes, such as the ones that are embedded in the rich text control to
show failed processes in red.

Do you know of a class that can process/manipulate rtf w/o rendering it?

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
If the culprit is the events perhaps you should rethink your design... and
use a shared or global variable to communicate state. The UI thread would
periodically check the status rather then the worker thread informing the
UI
via events.

"Charles Law" wrote:
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds.
Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less
than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed
time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than
25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I
am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears
to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from
the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute
time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
> "Charles Law" <bl***@nowhere.com> wrote in
> news:up**************@TK2MSFTNGP10.phx.gbl...
>> Hi Niki
>>
>> Thanks for the response. I currently display the absolute and elapsed
>> times using a high res timer, which is how I can see the difference
>> between the expected and actual timings. I guess I could add more time
>> displays, but it would generate a lot of output, and whilst it might
>> tell
>> me when and where in my code the excess time is taken, I am not sure
>> it
>> will necessarily tell me why. I don't think it is my code (they all
>> say
>> that), because it is so random.
>
> Is it really random? How can you know without knowing where it happens?
> I
> thought all you knew was that it doesn't happen every time?
>
> Did you analyze the time delta's? How are they distributed? Is there a
> normal distribution around 300 ms plus some peaks at 2,5 s? If so, did
> you
> check where those peaks are? (I always dump output like that to a text
> file and use Excel to analyze it later)
>
>>> - Monitor the .NET performance counters. Is there maybe some
>>> correlation
>>> to GC collection or some other runtime event?
>>
>> How can I tell when garbage collection occurs?
>
> I have a German windows version, so I can't tell you the exact name of
> the
> performance counter, should be something like "Number of GCs" in the
> ".NET
> Memory" performance counters section. It increases by one with each GC
> collection. Use perfmon to record it while you test your app.
>
>>> - Which GC do you use?
>>
>> How many are there? I thought there was just the one, built-in to the
>> framework.
>
> MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll)
> and
> Server (mscorsvr.dll). When running in Workstation mode, latency is
> more
> of a concern than space or efficiency. A server with multiple
> processors
> and clients connected over a network can afford some latency, but
> throughput is now a top priority. Rather than shoehorn both of these
> scenarios into a single GC scheme, Microsoft has included two garbage
> collectors that are tailored to each situation."
> [http://msdn.microsoft.com/library/de...perftechs.asp]
>
> You'll have to host the runtime to choose between the two, but I think
> the
> workstation version is the better choice for you anyway.
>
> Niki
>


Jul 21 '05 #28

P: n/a
Charles,
Is it possible to suspend garbage collection for critical sections? Unfortunately, or is it fortunately. No you cannot.

Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:uz**************@TK2MSFTNGP14.phx.gbl... Hi Jay

A lot of good information, as usual. I shall mull it over and try some of
this out.
Can you use CLR profiler or custom performance counters to identify that
a Garbage Collection is not occurring during this "critical" process? Can
you redesign the critical process to minimize garbage collections if this
is the problem?


Is it possible to suspend garbage collection for critical sections?
Are you certain that windows did not suspend your program in favor of
allowing another program to run?


There is nothing obviously getting control; very little else is running.
The m/c is not networked, and apart from Norton Antivirus - which is
disabled - there is nothing much else.
Have you tried using Thread.Priority and/or Process.PriorityClass &
Process.PriorityBoostEnabled so Windows will favor your thread/process?


I haven't, but I will take a look.

Cheers.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:%2****************@TK2MSFTNGP09.phx.gbl...
Charles,
This sounds like the ideal use of multiple threads!

I'm not sure what Cor was smoking when he responded :-|

However due to the nature of .NET (non-deterministic garbage collection)
& Windows preemptive scheduling; "real-time" critical processes are hard
to achieve.

Can you use CLR profiler or custom performance counters to identify that
a Garbage Collection is not occurring during this "critical" process? Can
you redesign the critical process to minimize garbage collections if this
is the problem?

Are you certain that windows did not suspend your program in favor of
allowing another program to run?

Have you tried using Thread.Priority and/or Process.PriorityClass &
Process.PriorityBoostEnabled so Windows will favor your thread/process?

WARNING: I would use Process.PriorityClass & Process.PriorityBoostEnabled
with extreme caution!

Info on the CLR Profiler:
http://msdn.microsoft.com/library/de...nethowto13.asp

http://msdn.microsoft.com/library/de...anagedapps.asp

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:uu***************@TK2MSFTNGP12.phx.gbl...
Hi guys

I have a time critical process, running on a worker thread. By "time
critical", I mean that certain parts of the process must be completed in
a specific time frame. The time when the process starts is not
especially important, but it must be complete within a small number of
seconds.

The operations I am performing do not take a long time (hundreds of
milliseconds), but as each part of the process is complete, my worker
thread raises an event that is handled by the UI thread, to update a
rich text control with details of the completed operation. I am using a
rich text box so that when a failure occurs I can colour the message
red.

The problem I have is that sometimes, for no apparent reason, a step in
my process takes an inordinate amount of time, e.g 2.5 seconds instead
of perhaps 300 ms. When this happens, the complete process overruns my
time frame, and it has to be repeated. When I repeat the process there
is every chance that it completes in a realistic time, and all is well.
If I stop outputting to the screen, I do not get the problem.

When updating the screen on the UI thread, I use BeginInvoke, to marshal
the operation to the correct thread, and so as not to hold up the worker
thread, but this does not seem to help.

I realise that Windows (XP in this case) is not the ideal o/s for this
type of application, but does anyone have any ideas about how I could
make my application more deterministic? I am not certain what is going
on in these 2.5 seconds, so it might be useful if I could find out, but
I am not sure how I would do that.

TIA

Charles



Jul 21 '05 #29

P: n/a
CMM,
Causing the UI thread to periodically check the status means that it would
need to use CPU time that the critical thread may need, I would think
Charles would want to minimize the amount of work other threads are using...

Using BeginInvoke means the UI thread will only update the status when the
critical thread made a change...

Just a thought
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
If the culprit is the events perhaps you should rethink your design... and
use a shared or global variable to communicate state. The UI thread would
periodically check the status rather then the worker thread informing the
UI
via events.

"Charles Law" wrote:
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds.
Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less
than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed
time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than
25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I
am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears
to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from
the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute
time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
> "Charles Law" <bl***@nowhere.com> wrote in
> news:up**************@TK2MSFTNGP10.phx.gbl...
>> Hi Niki
>>
>> Thanks for the response. I currently display the absolute and elapsed
>> times using a high res timer, which is how I can see the difference
>> between the expected and actual timings. I guess I could add more time
>> displays, but it would generate a lot of output, and whilst it might
>> tell
>> me when and where in my code the excess time is taken, I am not sure
>> it
>> will necessarily tell me why. I don't think it is my code (they all
>> say
>> that), because it is so random.
>
> Is it really random? How can you know without knowing where it happens?
> I
> thought all you knew was that it doesn't happen every time?
>
> Did you analyze the time delta's? How are they distributed? Is there a
> normal distribution around 300 ms plus some peaks at 2,5 s? If so, did
> you
> check where those peaks are? (I always dump output like that to a text
> file and use Excel to analyze it later)
>
>>> - Monitor the .NET performance counters. Is there maybe some
>>> correlation
>>> to GC collection or some other runtime event?
>>
>> How can I tell when garbage collection occurs?
>
> I have a German windows version, so I can't tell you the exact name of
> the
> performance counter, should be something like "Number of GCs" in the
> ".NET
> Memory" performance counters section. It increases by one with each GC
> collection. Use perfmon to record it while you test your app.
>
>>> - Which GC do you use?
>>
>> How many are there? I thought there was just the one, built-in to the
>> framework.
>
> MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll)
> and
> Server (mscorsvr.dll). When running in Workstation mode, latency is
> more
> of a concern than space or efficiency. A server with multiple
> processors
> and clients connected over a network can afford some latency, but
> throughput is now a top priority. Rather than shoehorn both of these
> scenarios into a single GC scheme, Microsoft has included two garbage
> collectors that are tailored to each situation."
> [http://msdn.microsoft.com/library/de...perftechs.asp]
>
> You'll have to host the runtime to choose between the two, but I think
> the
> workstation version is the better choice for you anyway.
>
> Niki
>


Jul 21 '05 #30

P: n/a
Charles,
Once you rule out other apps (NAV, Screen Savers), which you cannot really
do anything real about anyway (process priority may help, a little). CMM &
my suggestions of redesigning the critical part is what you will need to do.

If you decide to use GC.Collect be certain to read & adhere to Rule #1 at:

http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx
The following links may (or may not) help in the redesign:
http://blogs.msdn.com/ricom/

http://blogs.msdn.com/maoni/

(the above two blogs have a number of useful articles, check all the
articles).

http://msdn.microsoft.com/library/de...anagedapps.asp
http://blogs.msdn.com/junfeng/archiv...13/181534.aspx

I would consider recoding the critical thread in C++ if profiling proved
that the GC & managed code was the problem...

What parameters are on your events? I normally use EventArgs.Empty instead
of New EventArgs. If you have a custom EventArgs class, I would consider
making it read write & reusing a single instance for all events that may be
raised by the critical code. Assuming that the GC is the problem...

I thought CLR Profiling will identify if your critical code itself is taking
all the time or if another thread is getting all the time. In other words
when you critical thread takes 2.5 seconds, how much of that CPU time did
your critical thread get & how much did other threads get...

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:eO**************@tk2msftngp13.phx.gbl...
There are certainly points in my process where I could perform a garbage
collect w/o upsetting the timing, so I will try a gc.Collect there and see
what happens.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C3**********************************@microsof t.com...
1) Force a garbage collection when it won't interfere with your time
sensitive loop... using gc.Collect().
2) Use structures. These get allocated and deallocated on demand.
3) Reuse objects where possible rather than reinstantiating new ones.
Perhaps using some sort of object pool or something.

Hopefully someone here might have some more robust "hardcore" ways to
help.
The following article might help too...
-
http://msdn.microsoft.com/library/de...etgcbasics.asp
- http://msdn.microsoft.com/msdnmag/is...2/default.aspx

"Charles Law" wrote:
> 1) Run the application in release mode. Applications with debug symbol
> baggage tend to run slower.

It is currently running that way.

> 2) Boost the priority of the thread.

Currently set to AboveNormal.

> 3) I'm not sure if this is redundant with #2 but you can try
> increasing
> the
> application's priority. Via Task Manager, select the process and
> select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.

Not tried, but I am inclined to agree with you assessment.

> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.

Each task in the process is in a Try .. Catch block, and any exception
would
appear on screen. In this case I do not get any exception reported.

> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.

The data in these tasks are pretty constant, so I would expect the
exceptions to be constant too, if there are any. The extra time does not
always appear in the same place (or at all), but the data do not change.

>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type
> objects?).

This is certainly one of my concerns, but I am unsure how I can restrict
garbage collection to non-time sensitive areas of my code. And yes, I am
creating a lot of non-value types; mostly associated with the raising of
events.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F3**********************************@microsof t.com...
> 1) Run the application in release mode. Applications with debug symbol
> baggage tend to run slower.
> 2) Boost the priority of the thread.
> 3) I'm not sure if this is redundant with #2 but you can try
> increasing
> the
> application's priority. Via Task Manager, select the process and
> select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.
> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.
> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.
>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type
> objects?).
>
>
> "Charles Law" wrote:
>
>> Hi guys
>>
>> I have a time critical process, running on a worker thread. By "time
>> critical", I mean that certain parts of the process must be completed
>> in
>> a
>> specific time frame. The time when the process starts is not
>> especially
>> important, but it must be complete within a small number of seconds.
>>
>> The operations I am performing do not take a long time (hundreds of
>> milliseconds), but as each part of the process is complete, my worker
>> thread
>> raises an event that is handled by the UI thread, to update a rich
>> text
>> control with details of the completed operation. I am using a rich
>> text
>> box
>> so that when a failure occurs I can colour the message red.
>>
>> The problem I have is that sometimes, for no apparent reason, a step
>> in
>> my
>> process takes an inordinate amount of time, e.g 2.5 seconds instead
>> of
>> perhaps 300 ms. When this happens, the complete process overruns my
>> time
>> frame, and it has to be repeated. When I repeat the process there is
>> every
>> chance that it completes in a realistic time, and all is well. If I
>> stop
>> outputting to the screen, I do not get the problem.
>>
>> When updating the screen on the UI thread, I use BeginInvoke, to
>> marshal
>> the
>> operation to the correct thread, and so as not to hold up the worker
>> thread,
>> but this does not seem to help.
>>
>> I realise that Windows (XP in this case) is not the ideal o/s for
>> this
>> type
>> of application, but does anyone have any ideas about how I could make
>> my
>> application more deterministic? I am not certain what is going on in
>> these
>> 2.5 seconds, so it might be useful if I could find out, but I am not
>> sure
>> how I would do that.
>>
>> TIA
>>
>> Charles
>>
>>
>>


Jul 21 '05 #31

P: n/a
CMM
You're probably right. But, I would think that a simple thread Timer (rather
than a loop) in the UI is efficient enough to not steal CPU time from the
worker thread... and it might (or not) be more efficient than the event model
/ begininvoke he is using.

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
Causing the UI thread to periodically check the status means that it would
need to use CPU time that the critical thread may need, I would think
Charles would want to minimize the amount of work other threads are using...

Using BeginInvoke means the UI thread will only update the status when the
critical thread made a change...

Just a thought
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
If the culprit is the events perhaps you should rethink your design... and
use a shared or global variable to communicate state. The UI thread would
periodically check the status rather then the worker thread informing the
UI
via events.

"Charles Law" wrote:
It's random in the sense that it doesn't always happen during the same
operation, and sometimes it doesn't happen at all.

The worker thread, repeatedly, does things like this:

DoTask1
DoTask2
DoTask7
DoTask2

All these tasks have to be performed within a couple of seconds.
Nominally,
task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.

The expectation, therefore, is that the whole process is over in less
than 1
second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I can
discern. Therefore, the entire sequence takes longer than the allowed
time,
and the process fails. That said, it is not always task 1 that takes the
excess time; it could be task 2, or task 7, or task 43.

Each of these tasks will send and receive data on a serial port. I have
timed the serial comms carefully, and it consistently takes no more than
25
ms to send and receive data. Thus, I conclude that the time is spent
elsewhere.

Before each task is started, an event is raised to inform the UI that the
task is starting. The UI updates a rich text control using BeginInvoke. I
am
wondering if these requests to update the UI pile up, for example, and
eventually get flushed, holding up the worker thread. The screen appears
to
update steadily, but by definition the screen updates will not be
synchronised to the update requests, so some of them might result from
the
clearing of a backlog.

When the UI displays the task being performed, I display the absolute
time
and the delta based on a high res counter.

I will have a look at the performance counter you mention.

Charles
"Niki Estner" <ni*********@cube.net> wrote in message
news:OW**************@TK2MSFTNGP12.phx.gbl...
> "Charles Law" <bl***@nowhere.com> wrote in
> news:up**************@TK2MSFTNGP10.phx.gbl...
>> Hi Niki
>>
>> Thanks for the response. I currently display the absolute and elapsed
>> times using a high res timer, which is how I can see the difference
>> between the expected and actual timings. I guess I could add more time
>> displays, but it would generate a lot of output, and whilst it might
>> tell
>> me when and where in my code the excess time is taken, I am not sure
>> it
>> will necessarily tell me why. I don't think it is my code (they all
>> say
>> that), because it is so random.
>
> Is it really random? How can you know without knowing where it happens?
> I
> thought all you knew was that it doesn't happen every time?
>
> Did you analyze the time delta's? How are they distributed? Is there a
> normal distribution around 300 ms plus some peaks at 2,5 s? If so, did
> you
> check where those peaks are? (I always dump output like that to a text
> file and use Excel to analyze it later)
>
>>> - Monitor the .NET performance counters. Is there maybe some
>>> correlation
>>> to GC collection or some other runtime event?
>>
>> How can I tell when garbage collection occurs?
>
> I have a German windows version, so I can't tell you the exact name of
> the
> performance counter, should be something like "Number of GCs" in the
> ".NET
> Memory" performance counters section. It increases by one with each GC
> collection. Use perfmon to record it while you test your app.
>
>>> - Which GC do you use?
>>
>> How many are there? I thought there was just the one, built-in to the
>> framework.
>
> MSDN Quote: "The CLR has two different GCs: Workstation (mscorwks.dll)
> and
> Server (mscorsvr.dll). When running in Workstation mode, latency is
> more
> of a concern than space or efficiency. A server with multiple
> processors
> and clients connected over a network can afford some latency, but
> throughput is now a top priority. Rather than shoehorn both of these
> scenarios into a single GC scheme, Microsoft has included two garbage
> collectors that are tailored to each situation."
> [http://msdn.microsoft.com/library/de...perftechs.asp]
>
> You'll have to host the runtime to choose between the two, but I think
> the
> workstation version is the better choice for you anyway.
>
> Niki
>


Jul 21 '05 #32

P: n/a
CMM,
What do you mean by "thread Timer"? Remember there are three timers in .NET.

- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer

The first two you will need to use BeginInvoke either directly or
indirectly, so I don't really see any potential "win" there. While the third
will be on the UI thread.

My point is in all three cases the UI thread will be exectuting code when it
could simply wait for the BeginInvoke from the critical thread...

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:3B**********************************@microsof t.com...
You're probably right. But, I would think that a simple thread Timer
(rather
than a loop) in the UI is efficient enough to not steal CPU time from the
worker thread... and it might (or not) be more efficient than the event
model
/ begininvoke he is using.

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
Causing the UI thread to periodically check the status means that it
would
need to use CPU time that the critical thread may need, I would think
Charles would want to minimize the amount of work other threads are
using...

Using BeginInvoke means the UI thread will only update the status when
the
critical thread made a change...

Just a thought
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
> If the culprit is the events perhaps you should rethink your design...
> and
> use a shared or global variable to communicate state. The UI thread
> would
> periodically check the status rather then the worker thread informing
> the
> UI
> via events.
>
> "Charles Law" wrote:
>
>> It's random in the sense that it doesn't always happen during the same
>> operation, and sometimes it doesn't happen at all.
>>
>> The worker thread, repeatedly, does things like this:
>>
>> DoTask1
>> DoTask2
>> DoTask7
>> DoTask2
>>
>> All these tasks have to be performed within a couple of seconds.
>> Nominally,
>> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.
>>
>> The expectation, therefore, is that the whole process is over in less
>> than 1
>> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I
>> can
>> discern. Therefore, the entire sequence takes longer than the allowed
>> time,
>> and the process fails. That said, it is not always task 1 that takes
>> the
>> excess time; it could be task 2, or task 7, or task 43.
>>
>> Each of these tasks will send and receive data on a serial port. I
>> have
>> timed the serial comms carefully, and it consistently takes no more
>> than
>> 25
>> ms to send and receive data. Thus, I conclude that the time is spent
>> elsewhere.
>>
>> Before each task is started, an event is raised to inform the UI that
>> the
>> task is starting. The UI updates a rich text control using
>> BeginInvoke. I
>> am
>> wondering if these requests to update the UI pile up, for example, and
>> eventually get flushed, holding up the worker thread. The screen
>> appears
>> to
>> update steadily, but by definition the screen updates will not be
>> synchronised to the update requests, so some of them might result from
>> the
>> clearing of a backlog.
>>
>> When the UI displays the task being performed, I display the absolute
>> time
>> and the delta based on a high res counter.
>>
>> I will have a look at the performance counter you mention.
>>
>> Charles
>>
>>
>> "Niki Estner" <ni*********@cube.net> wrote in message
>> news:OW**************@TK2MSFTNGP12.phx.gbl...
>> > "Charles Law" <bl***@nowhere.com> wrote in
>> > news:up**************@TK2MSFTNGP10.phx.gbl...
>> >> Hi Niki
>> >>
>> >> Thanks for the response. I currently display the absolute and
>> >> elapsed
>> >> times using a high res timer, which is how I can see the difference
>> >> between the expected and actual timings. I guess I could add more
>> >> time
>> >> displays, but it would generate a lot of output, and whilst it
>> >> might
>> >> tell
>> >> me when and where in my code the excess time is taken, I am not
>> >> sure
>> >> it
>> >> will necessarily tell me why. I don't think it is my code (they all
>> >> say
>> >> that), because it is so random.
>> >
>> > Is it really random? How can you know without knowing where it
>> > happens?
>> > I
>> > thought all you knew was that it doesn't happen every time?
>> >
>> > Did you analyze the time delta's? How are they distributed? Is there
>> > a
>> > normal distribution around 300 ms plus some peaks at 2,5 s? If so,
>> > did
>> > you
>> > check where those peaks are? (I always dump output like that to a
>> > text
>> > file and use Excel to analyze it later)
>> >
>> >>> - Monitor the .NET performance counters. Is there maybe some
>> >>> correlation
>> >>> to GC collection or some other runtime event?
>> >>
>> >> How can I tell when garbage collection occurs?
>> >
>> > I have a German windows version, so I can't tell you the exact name
>> > of
>> > the
>> > performance counter, should be something like "Number of GCs" in the
>> > ".NET
>> > Memory" performance counters section. It increases by one with each
>> > GC
>> > collection. Use perfmon to record it while you test your app.
>> >
>> >>> - Which GC do you use?
>> >>
>> >> How many are there? I thought there was just the one, built-in to
>> >> the
>> >> framework.
>> >
>> > MSDN Quote: "The CLR has two different GCs: Workstation
>> > (mscorwks.dll)
>> > and
>> > Server (mscorsvr.dll). When running in Workstation mode, latency is
>> > more
>> > of a concern than space or efficiency. A server with multiple
>> > processors
>> > and clients connected over a network can afford some latency, but
>> > throughput is now a top priority. Rather than shoehorn both of these
>> > scenarios into a single GC scheme, Microsoft has included two
>> > garbage
>> > collectors that are tailored to each situation."
>> > [http://msdn.microsoft.com/library/de...perftechs.asp]
>> >
>> > You'll have to host the runtime to choose between the two, but I
>> > think
>> > the
>> > workstation version is the better choice for you anyway.
>> >
>> > Niki
>> >
>>
>>
>>


Jul 21 '05 #33

P: n/a
CMM
I'd use the forms timer component as it's the best suited for this purpose...
he's after all updating a form :-) ... set to some reasonable interval that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's doing-
is not without expense. A third thread has to be picked up from the pool or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might prove
detrimental to his worker thread. There's no guarantee that the work done by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
What do you mean by "thread Timer"? Remember there are three timers in .NET.

- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer

The first two you will need to use BeginInvoke either directly or
indirectly, so I don't really see any potential "win" there. While the third
will be on the UI thread.

My point is in all three cases the UI thread will be exectuting code when it
could simply wait for the BeginInvoke from the critical thread...

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:3B**********************************@microsof t.com...
You're probably right. But, I would think that a simple thread Timer
(rather
than a loop) in the UI is efficient enough to not steal CPU time from the
worker thread... and it might (or not) be more efficient than the event
model
/ begininvoke he is using.

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
Causing the UI thread to periodically check the status means that it
would
need to use CPU time that the critical thread may need, I would think
Charles would want to minimize the amount of work other threads are
using...

Using BeginInvoke means the UI thread will only update the status when
the
critical thread made a change...

Just a thought
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
> If the culprit is the events perhaps you should rethink your design...
> and
> use a shared or global variable to communicate state. The UI thread
> would
> periodically check the status rather then the worker thread informing
> the
> UI
> via events.
>
> "Charles Law" wrote:
>
>> It's random in the sense that it doesn't always happen during the same
>> operation, and sometimes it doesn't happen at all.
>>
>> The worker thread, repeatedly, does things like this:
>>
>> DoTask1
>> DoTask2
>> DoTask7
>> DoTask2
>>
>> All these tasks have to be performed within a couple of seconds.
>> Nominally,
>> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.
>>
>> The expectation, therefore, is that the whole process is over in less
>> than 1
>> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I
>> can
>> discern. Therefore, the entire sequence takes longer than the allowed
>> time,
>> and the process fails. That said, it is not always task 1 that takes
>> the
>> excess time; it could be task 2, or task 7, or task 43.
>>
>> Each of these tasks will send and receive data on a serial port. I
>> have
>> timed the serial comms carefully, and it consistently takes no more
>> than
>> 25
>> ms to send and receive data. Thus, I conclude that the time is spent
>> elsewhere.
>>
>> Before each task is started, an event is raised to inform the UI that
>> the
>> task is starting. The UI updates a rich text control using
>> BeginInvoke. I
>> am
>> wondering if these requests to update the UI pile up, for example, and
>> eventually get flushed, holding up the worker thread. The screen
>> appears
>> to
>> update steadily, but by definition the screen updates will not be
>> synchronised to the update requests, so some of them might result from
>> the
>> clearing of a backlog.
>>
>> When the UI displays the task being performed, I display the absolute
>> time
>> and the delta based on a high res counter.
>>
>> I will have a look at the performance counter you mention.
>>
>> Charles
>>
>>
>> "Niki Estner" <ni*********@cube.net> wrote in message
>> news:OW**************@TK2MSFTNGP12.phx.gbl...
>> > "Charles Law" <bl***@nowhere.com> wrote in
>> > news:up**************@TK2MSFTNGP10.phx.gbl...
>> >> Hi Niki
>> >>
>> >> Thanks for the response. I currently display the absolute and
>> >> elapsed
>> >> times using a high res timer, which is how I can see the difference
>> >> between the expected and actual timings. I guess I could add more
>> >> time
>> >> displays, but it would generate a lot of output, and whilst it
>> >> might
>> >> tell
>> >> me when and where in my code the excess time is taken, I am not
>> >> sure
>> >> it
>> >> will necessarily tell me why. I don't think it is my code (they all
>> >> say
>> >> that), because it is so random.
>> >
>> > Is it really random? How can you know without knowing where it
>> > happens?
>> > I
>> > thought all you knew was that it doesn't happen every time?
>> >
>> > Did you analyze the time delta's? How are they distributed? Is there
>> > a
>> > normal distribution around 300 ms plus some peaks at 2,5 s? If so,
>> > did
>> > you
>> > check where those peaks are? (I always dump output like that to a
>> > text
>> > file and use Excel to analyze it later)
>> >
>> >>> - Monitor the .NET performance counters. Is there maybe some
>> >>> correlation
>> >>> to GC collection or some other runtime event?
>> >>
>> >> How can I tell when garbage collection occurs?
>> >
>> > I have a German windows version, so I can't tell you the exact name
>> > of
>> > the
>> > performance counter, should be something like "Number of GCs" in the
>> > ".NET
>> > Memory" performance counters section. It increases by one with each
>> > GC
>> > collection. Use perfmon to record it while you test your app.
>> >
>> >>> - Which GC do you use?
>> >>
>> >> How many are there? I thought there was just the one, built-in to
>> >> the
>> >> framework.
>> >
>> > MSDN Quote: "The CLR has two different GCs: Workstation
>> > (mscorwks.dll)
>> > and
>> > Server (mscorsvr.dll). When running in Workstation mode, latency is
>> > more
>> > of a concern than space or efficiency. A server with multiple
>> > processors
>> > and clients connected over a network can afford some latency, but
>> > throughput is now a top priority. Rather than shoehorn both of these
>> > scenarios into a single GC scheme, Microsoft has included two
>> > garbage
>> > collectors that are tailored to each situation."
>> > [http://msdn.microsoft.com/library/de...perftechs.asp]
>> >
>> > You'll have to host the runtime to choose between the two, but I
>> > think
>> > the
>> > workstation version is the better choice for you anyway.
>> >
>> > Niki
>> >
>>
>>
>>


Jul 21 '05 #34

P: n/a
CMM
To clarify.... After thinking about it I realize that the timer model might
have the same problems as the BeginInvoke model. However, it might still
alleviate the worker thread somewhat. Like I said... and AFAIK... when
BeginInvoke is called the framework has to spawn a thread momentarily in
order to return execution to the caller "immediately" before marshalling the
call to the UI thread. This means that execution is not really really
returned to the caller "immediately." Why should the worker thread incur this
expense? Let the UI thread deal with it (via the Timer).

Alas, in the end... I strongly suspect that your advice to use
EventArgs.Empty or *reuse* a custom eventargs object (with settable
properties) rather than reinstantiating a new one would (coupled with well
placed gc.Collects) help his problem more than any changes to his
Event/BeginInvoke technique.
"CMM" wrote:
I'd use the forms timer component as it's the best suited for this purpose...
he's after all updating a form :-) ... set to some reasonable interval that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's doing-
is not without expense. A third thread has to be picked up from the pool or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might prove
detrimental to his worker thread. There's no guarantee that the work done by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
What do you mean by "thread Timer"? Remember there are three timers in .NET.

- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer

The first two you will need to use BeginInvoke either directly or
indirectly, so I don't really see any potential "win" there. While the third
will be on the UI thread.

My point is in all three cases the UI thread will be exectuting code when it
could simply wait for the BeginInvoke from the critical thread...

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:3B**********************************@microsof t.com...
You're probably right. But, I would think that a simple thread Timer
(rather
than a loop) in the UI is efficient enough to not steal CPU time from the
worker thread... and it might (or not) be more efficient than the event
model
/ begininvoke he is using.

"Jay B. Harlow [MVP - Outlook]" wrote:

> CMM,
> Causing the UI thread to periodically check the status means that it
> would
> need to use CPU time that the critical thread may need, I would think
> Charles would want to minimize the amount of work other threads are
> using...
>
> Using BeginInvoke means the UI thread will only update the status when
> the
> critical thread made a change...
>
> Just a thought
> Jay
>
> "CMM" <CM*@discussions.microsoft.com> wrote in message
> news:97**********************************@microsof t.com...
> > If the culprit is the events perhaps you should rethink your design...
> > and
> > use a shared or global variable to communicate state. The UI thread
> > would
> > periodically check the status rather then the worker thread informing
> > the
> > UI
> > via events.
> >
> > "Charles Law" wrote:
> >
> >> It's random in the sense that it doesn't always happen during the same
> >> operation, and sometimes it doesn't happen at all.
> >>
> >> The worker thread, repeatedly, does things like this:
> >>
> >> DoTask1
> >> DoTask2
> >> DoTask7
> >> DoTask2
> >>
> >> All these tasks have to be performed within a couple of seconds.
> >> Nominally,
> >> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.
> >>
> >> The expectation, therefore, is that the whole process is over in less
> >> than 1
> >> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I
> >> can
> >> discern. Therefore, the entire sequence takes longer than the allowed
> >> time,
> >> and the process fails. That said, it is not always task 1 that takes
> >> the
> >> excess time; it could be task 2, or task 7, or task 43.
> >>
> >> Each of these tasks will send and receive data on a serial port. I
> >> have
> >> timed the serial comms carefully, and it consistently takes no more
> >> than
> >> 25
> >> ms to send and receive data. Thus, I conclude that the time is spent
> >> elsewhere.
> >>
> >> Before each task is started, an event is raised to inform the UI that
> >> the
> >> task is starting. The UI updates a rich text control using
> >> BeginInvoke. I
> >> am
> >> wondering if these requests to update the UI pile up, for example, and
> >> eventually get flushed, holding up the worker thread. The screen
> >> appears
> >> to
> >> update steadily, but by definition the screen updates will not be
> >> synchronised to the update requests, so some of them might result from
> >> the
> >> clearing of a backlog.
> >>
> >> When the UI displays the task being performed, I display the absolute
> >> time
> >> and the delta based on a high res counter.
> >>
> >> I will have a look at the performance counter you mention.
> >>
> >> Charles
> >>
> >>
> >> "Niki Estner" <ni*********@cube.net> wrote in message
> >> news:OW**************@TK2MSFTNGP12.phx.gbl...
> >> > "Charles Law" <bl***@nowhere.com> wrote in
> >> > news:up**************@TK2MSFTNGP10.phx.gbl...
> >> >> Hi Niki
> >> >>
> >> >> Thanks for the response. I currently display the absolute and
> >> >> elapsed
> >> >> times using a high res timer, which is how I can see the difference
> >> >> between the expected and actual timings. I guess I could add more
> >> >> time
> >> >> displays, but it would generate a lot of output, and whilst it
> >> >> might
> >> >> tell
> >> >> me when and where in my code the excess time is taken, I am not
> >> >> sure
> >> >> it
> >> >> will necessarily tell me why. I don't think it is my code (they all
> >> >> say
> >> >> that), because it is so random.
> >> >
> >> > Is it really random? How can you know without knowing where it
> >> > happens?
> >> > I
> >> > thought all you knew was that it doesn't happen every time?
> >> >
> >> > Did you analyze the time delta's? How are they distributed? Is there
> >> > a
> >> > normal distribution around 300 ms plus some peaks at 2,5 s? If so,
> >> > did
> >> > you
> >> > check where those peaks are? (I always dump output like that to a
> >> > text
> >> > file and use Excel to analyze it later)
> >> >
> >> >>> - Monitor the .NET performance counters. Is there maybe some
> >> >>> correlation
> >> >>> to GC collection or some other runtime event?
> >> >>
> >> >> How can I tell when garbage collection occurs?
> >> >
> >> > I have a German windows version, so I can't tell you the exact name
> >> > of
> >> > the
> >> > performance counter, should be something like "Number of GCs" in the
> >> > ".NET
> >> > Memory" performance counters section. It increases by one with each
> >> > GC
> >> > collection. Use perfmon to record it while you test your app.
> >> >
> >> >>> - Which GC do you use?
> >> >>
> >> >> How many are there? I thought there was just the one, built-in to
> >> >> the
> >> >> framework.
> >> >
> >> > MSDN Quote: "The CLR has two different GCs: Workstation
> >> > (mscorwks.dll)
> >> > and
> >> > Server (mscorsvr.dll). When running in Workstation mode, latency is
> >> > more
> >> > of a concern than space or efficiency. A server with multiple
> >> > processors
> >> > and clients connected over a network can afford some latency, but
> >> > throughput is now a top priority. Rather than shoehorn both of these
> >> > scenarios into a single GC scheme, Microsoft has included two
> >> > garbage
> >> > collectors that are tailored to each situation."
> >> > [http://msdn.microsoft.com/library/de...perftechs.asp]
> >> >
> >> > You'll have to host the runtime to choose between the two, but I
> >> > think
> >> > the
> >> > workstation version is the better choice for you anyway.
> >> >
> >> > Niki
> >> >
> >>
> >>
> >>
>
>
>


Jul 21 '05 #35

P: n/a
CMM,
when
BeginInvoke is called the framework has to spawn a thread momentarily in
order to return execution to the caller "immediately" Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!

As long as you are not crossing an AppDomain my understanding is that no
real "marshalling" takes place either.

I would however expect the parameters to BeginInvoke to be "packaged" in an
"invoke" queue. This "invoke" queue could be the Win32 message queue, or it
could be a delegate & a parameters queue. This packaging in an invoke queue,
might not be any longer then your putting the information on a stack...

I would favor events due to the 80/20 rule, and I would use profiling to
identify if BeginInvoke was truly the bottleneck...

Remember that most programs follow the 80/20 rule (link below) that is 80%
of the execution time of your program is spent in 20% of your code. I will
optimize the 20% once that 20% has been identified & proven to be a
performance problem via profiling (see CLR Profiler in my other message).

For info on the 80/20 rule & optimizing only the 20% see Martin Fowler's
article "Yet Another Optimization Article" at
http://martinfowler.com/ieeeSoftware...timization.pdf

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:40**********************************@microsof t.com... To clarify.... After thinking about it I realize that the timer model
might
have the same problems as the BeginInvoke model. However, it might still
alleviate the worker thread somewhat. Like I said... and AFAIK... when
BeginInvoke is called the framework has to spawn a thread momentarily in
order to return execution to the caller "immediately" before marshalling
the
call to the UI thread. This means that execution is not really really
returned to the caller "immediately." Why should the worker thread incur
this
expense? Let the UI thread deal with it (via the Timer).

Alas, in the end... I strongly suspect that your advice to use
EventArgs.Empty or *reuse* a custom eventargs object (with settable
properties) rather than reinstantiating a new one would (coupled with well
placed gc.Collects) help his problem more than any changes to his
Event/BeginInvoke technique.
"CMM" wrote:
I'd use the forms timer component as it's the best suited for this
purpose...
he's after all updating a form :-) ... set to some reasonable interval
that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's
doing-
is not without expense. A third thread has to be picked up from the pool
or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might
prove
detrimental to his worker thread. There's no guarantee that the work done
by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to
me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and
then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:
> CMM,
> What do you mean by "thread Timer"? Remember there are three timers in
> .NET.
>
> - System.Threading.Timer
> - System.Timers.Timer
> - System.Windows.Forms.Timer
>
> The first two you will need to use BeginInvoke either directly or
> indirectly, so I don't really see any potential "win" there. While the
> third
> will be on the UI thread.
>
> My point is in all three cases the UI thread will be exectuting code
> when it
> could simply wait for the BeginInvoke from the critical thread...
>
> Hope this helps
> Jay
>
>
> "CMM" <CM*@discussions.microsoft.com> wrote in message
> news:3B**********************************@microsof t.com...
> > You're probably right. But, I would think that a simple thread Timer
> > (rather
> > than a loop) in the UI is efficient enough to not steal CPU time from
> > the
> > worker thread... and it might (or not) be more efficient than the
> > event
> > model
> > / begininvoke he is using.
> >
> > "Jay B. Harlow [MVP - Outlook]" wrote:
> >
> >> CMM,
> >> Causing the UI thread to periodically check the status means that it
> >> would
> >> need to use CPU time that the critical thread may need, I would
> >> think
> >> Charles would want to minimize the amount of work other threads are
> >> using...
> >>
> >> Using BeginInvoke means the UI thread will only update the status
> >> when
> >> the
> >> critical thread made a change...
> >>
> >> Just a thought
> >> Jay
> >>
> >> "CMM" <CM*@discussions.microsoft.com> wrote in message
> >> news:97**********************************@microsof t.com...
> >> > If the culprit is the events perhaps you should rethink your
> >> > design...
> >> > and
> >> > use a shared or global variable to communicate state. The UI
> >> > thread
> >> > would
> >> > periodically check the status rather then the worker thread
> >> > informing
> >> > the
> >> > UI
> >> > via events.
> >> >
> >> > "Charles Law" wrote:
> >> >
> >> >> It's random in the sense that it doesn't always happen during the
> >> >> same
> >> >> operation, and sometimes it doesn't happen at all.
> >> >>
> >> >> The worker thread, repeatedly, does things like this:
> >> >>
> >> >> DoTask1
> >> >> DoTask2
> >> >> DoTask7
> >> >> DoTask2
> >> >>
> >> >> All these tasks have to be performed within a couple of seconds.
> >> >> Nominally,
> >> >> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms,
> >> >> say.
> >> >>
> >> >> The expectation, therefore, is that the whole process is over in
> >> >> less
> >> >> than 1
> >> >> second. Sometimes, though, task 1 takes 2.5 seconds, for no
> >> >> reason I
> >> >> can
> >> >> discern. Therefore, the entire sequence takes longer than the
> >> >> allowed
> >> >> time,
> >> >> and the process fails. That said, it is not always task 1 that
> >> >> takes
> >> >> the
> >> >> excess time; it could be task 2, or task 7, or task 43.
> >> >>
> >> >> Each of these tasks will send and receive data on a serial port.
> >> >> I
> >> >> have
> >> >> timed the serial comms carefully, and it consistently takes no
> >> >> more
> >> >> than
> >> >> 25
> >> >> ms to send and receive data. Thus, I conclude that the time is
> >> >> spent
> >> >> elsewhere.
> >> >>
> >> >> Before each task is started, an event is raised to inform the UI
> >> >> that
> >> >> the
> >> >> task is starting. The UI updates a rich text control using
> >> >> BeginInvoke. I
> >> >> am
> >> >> wondering if these requests to update the UI pile up, for
> >> >> example, and
> >> >> eventually get flushed, holding up the worker thread. The screen
> >> >> appears
> >> >> to
> >> >> update steadily, but by definition the screen updates will not be
> >> >> synchronised to the update requests, so some of them might result
> >> >> from
> >> >> the
> >> >> clearing of a backlog.
> >> >>
> >> >> When the UI displays the task being performed, I display the
> >> >> absolute
> >> >> time
> >> >> and the delta based on a high res counter.
> >> >>
> >> >> I will have a look at the performance counter you mention.
> >> >>
> >> >> Charles
> >> >>
> >> >>
> >> >> "Niki Estner" <ni*********@cube.net> wrote in message
> >> >> news:OW**************@TK2MSFTNGP12.phx.gbl...
> >> >> > "Charles Law" <bl***@nowhere.com> wrote in
> >> >> > news:up**************@TK2MSFTNGP10.phx.gbl...
> >> >> >> Hi Niki
> >> >> >>
> >> >> >> Thanks for the response. I currently display the absolute and
> >> >> >> elapsed
> >> >> >> times using a high res timer, which is how I can see the
> >> >> >> difference
> >> >> >> between the expected and actual timings. I guess I could add
> >> >> >> more
> >> >> >> time
> >> >> >> displays, but it would generate a lot of output, and whilst it
> >> >> >> might
> >> >> >> tell
> >> >> >> me when and where in my code the excess time is taken, I am
> >> >> >> not
> >> >> >> sure
> >> >> >> it
> >> >> >> will necessarily tell me why. I don't think it is my code
> >> >> >> (they all
> >> >> >> say
> >> >> >> that), because it is so random.
> >> >> >
> >> >> > Is it really random? How can you know without knowing where it
> >> >> > happens?
> >> >> > I
> >> >> > thought all you knew was that it doesn't happen every time?
> >> >> >
> >> >> > Did you analyze the time delta's? How are they distributed? Is
> >> >> > there
> >> >> > a
> >> >> > normal distribution around 300 ms plus some peaks at 2,5 s? If
> >> >> > so,
> >> >> > did
> >> >> > you
> >> >> > check where those peaks are? (I always dump output like that to
> >> >> > a
> >> >> > text
> >> >> > file and use Excel to analyze it later)
> >> >> >
> >> >> >>> - Monitor the .NET performance counters. Is there maybe some
> >> >> >>> correlation
> >> >> >>> to GC collection or some other runtime event?
> >> >> >>
> >> >> >> How can I tell when garbage collection occurs?
> >> >> >
> >> >> > I have a German windows version, so I can't tell you the exact
> >> >> > name
> >> >> > of
> >> >> > the
> >> >> > performance counter, should be something like "Number of GCs"
> >> >> > in the
> >> >> > ".NET
> >> >> > Memory" performance counters section. It increases by one with
> >> >> > each
> >> >> > GC
> >> >> > collection. Use perfmon to record it while you test your app.
> >> >> >
> >> >> >>> - Which GC do you use?
> >> >> >>
> >> >> >> How many are there? I thought there was just the one, built-in
> >> >> >> to
> >> >> >> the
> >> >> >> framework.
> >> >> >
> >> >> > MSDN Quote: "The CLR has two different GCs: Workstation
> >> >> > (mscorwks.dll)
> >> >> > and
> >> >> > Server (mscorsvr.dll). When running in Workstation mode,
> >> >> > latency is
> >> >> > more
> >> >> > of a concern than space or efficiency. A server with multiple
> >> >> > processors
> >> >> > and clients connected over a network can afford some latency,
> >> >> > but
> >> >> > throughput is now a top priority. Rather than shoehorn both of
> >> >> > these
> >> >> > scenarios into a single GC scheme, Microsoft has included two
> >> >> > garbage
> >> >> > collectors that are tailored to each situation."
> >> >> > [http://msdn.microsoft.com/library/de...perftechs.asp]
> >> >> >
> >> >> > You'll have to host the runtime to choose between the two, but
> >> >> > I
> >> >> > think
> >> >> > the
> >> >> > workstation version is the better choice for you anyway.
> >> >> >
> >> >> > Niki
> >> >> >
> >> >>
> >> >>
> >> >>
> >>
> >>
> >>
>
>
>

Jul 21 '05 #36

P: n/a
CMM,
Its seems that we are discussing the benefits of Polling over the benefits
on Events. In my experience Events are almost always better then polling!
Hence my comments... Yes polling may be better here, however I would use the
80

The "don't call us, we'll call you" pattern if you will. :-)

The fact that one object exists "in" a critical thread, while the second
object exists "in" the UI is largely immaterial. I would have the object
that exists in the critical object, simply raise one or more events to
notify others that something significant occured, then continually "pester"
it to see if it changed... Other objects such as the Form would handle these
events. In the case of worker thread & UI thread, a Form/Control on the UI
thread itself would use IsInvokeRequired to decide if the BeginInvoked
needed to be called or not.

Now because the "BeginInvoke" is encapsulated in the Form itself, if
profiling demonstrated that it was the bottle neck, then I can simply change
the form to use a Timer or other method to allow the critical thread to
notify the UI thread of changes...
In VS.NET 2005 (.NET 2.0 aka Whidbey, due out later in 2005) there is the
BackgroundWorker class that will simplify allowing a worker thread (object)
notify the UI thread (object) about "significant" events (progress changed &
completed). Basically a Mediator between the UI object/thread and the worker
object/thread...

http://msdn2.microsoft.com/library/4852et58.aspx

So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye. ??

I am referring to Control.BeginInvoke not Delegate.BeginInvoke, no threads
are created/taken & released from the thread pool!

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:98**********************************@microsof t.com... I'd use the forms timer component as it's the best suited for this
purpose...
he's after all updating a form :-) ... set to some reasonable interval
that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's
doing-
is not without expense. A third thread has to be picked up from the pool
or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might
prove
detrimental to his worker thread. There's no guarantee that the work done
by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to
me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
What do you mean by "thread Timer"? Remember there are three timers in
.NET.

- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer

The first two you will need to use BeginInvoke either directly or
indirectly, so I don't really see any potential "win" there. While the
third
will be on the UI thread.

My point is in all three cases the UI thread will be exectuting code when
it
could simply wait for the BeginInvoke from the critical thread...

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:3B**********************************@microsof t.com...
> You're probably right. But, I would think that a simple thread Timer
> (rather
> than a loop) in the UI is efficient enough to not steal CPU time from
> the
> worker thread... and it might (or not) be more efficient than the event
> model
> / begininvoke he is using.
>
> "Jay B. Harlow [MVP - Outlook]" wrote:
>
>> CMM,
>> Causing the UI thread to periodically check the status means that it
>> would
>> need to use CPU time that the critical thread may need, I would think
>> Charles would want to minimize the amount of work other threads are
>> using...
>>
>> Using BeginInvoke means the UI thread will only update the status when
>> the
>> critical thread made a change...
>>
>> Just a thought
>> Jay
>>
>> "CMM" <CM*@discussions.microsoft.com> wrote in message
>> news:97**********************************@microsof t.com...
>> > If the culprit is the events perhaps you should rethink your
>> > design...
>> > and
>> > use a shared or global variable to communicate state. The UI thread
>> > would
>> > periodically check the status rather then the worker thread
>> > informing
>> > the
>> > UI
>> > via events.
>> >
>> > "Charles Law" wrote:
>> >
>> >> It's random in the sense that it doesn't always happen during the
>> >> same
>> >> operation, and sometimes it doesn't happen at all.
>> >>
>> >> The worker thread, repeatedly, does things like this:
>> >>
>> >> DoTask1
>> >> DoTask2
>> >> DoTask7
>> >> DoTask2
>> >>
>> >> All these tasks have to be performed within a couple of seconds.
>> >> Nominally,
>> >> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms,
>> >> say.
>> >>
>> >> The expectation, therefore, is that the whole process is over in
>> >> less
>> >> than 1
>> >> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason
>> >> I
>> >> can
>> >> discern. Therefore, the entire sequence takes longer than the
>> >> allowed
>> >> time,
>> >> and the process fails. That said, it is not always task 1 that
>> >> takes
>> >> the
>> >> excess time; it could be task 2, or task 7, or task 43.
>> >>
>> >> Each of these tasks will send and receive data on a serial port. I
>> >> have
>> >> timed the serial comms carefully, and it consistently takes no more
>> >> than
>> >> 25
>> >> ms to send and receive data. Thus, I conclude that the time is
>> >> spent
>> >> elsewhere.
>> >>
>> >> Before each task is started, an event is raised to inform the UI
>> >> that
>> >> the
>> >> task is starting. The UI updates a rich text control using
>> >> BeginInvoke. I
>> >> am
>> >> wondering if these requests to update the UI pile up, for example,
>> >> and
>> >> eventually get flushed, holding up the worker thread. The screen
>> >> appears
>> >> to
>> >> update steadily, but by definition the screen updates will not be
>> >> synchronised to the update requests, so some of them might result
>> >> from
>> >> the
>> >> clearing of a backlog.
>> >>
>> >> When the UI displays the task being performed, I display the
>> >> absolute
>> >> time
>> >> and the delta based on a high res counter.
>> >>
>> >> I will have a look at the performance counter you mention.
>> >>
>> >> Charles
>> >>
>> >>
>> >> "Niki Estner" <ni*********@cube.net> wrote in message
>> >> news:OW**************@TK2MSFTNGP12.phx.gbl...
>> >> > "Charles Law" <bl***@nowhere.com> wrote in
>> >> > news:up**************@TK2MSFTNGP10.phx.gbl...
>> >> >> Hi Niki
>> >> >>
>> >> >> Thanks for the response. I currently display the absolute and
>> >> >> elapsed
>> >> >> times using a high res timer, which is how I can see the
>> >> >> difference
>> >> >> between the expected and actual timings. I guess I could add
>> >> >> more
>> >> >> time
>> >> >> displays, but it would generate a lot of output, and whilst it
>> >> >> might
>> >> >> tell
>> >> >> me when and where in my code the excess time is taken, I am not
>> >> >> sure
>> >> >> it
>> >> >> will necessarily tell me why. I don't think it is my code (they
>> >> >> all
>> >> >> say
>> >> >> that), because it is so random.
>> >> >
>> >> > Is it really random? How can you know without knowing where it
>> >> > happens?
>> >> > I
>> >> > thought all you knew was that it doesn't happen every time?
>> >> >
>> >> > Did you analyze the time delta's? How are they distributed? Is
>> >> > there
>> >> > a
>> >> > normal distribution around 300 ms plus some peaks at 2,5 s? If
>> >> > so,
>> >> > did
>> >> > you
>> >> > check where those peaks are? (I always dump output like that to a
>> >> > text
>> >> > file and use Excel to analyze it later)
>> >> >
>> >> >>> - Monitor the .NET performance counters. Is there maybe some
>> >> >>> correlation
>> >> >>> to GC collection or some other runtime event?
>> >> >>
>> >> >> How can I tell when garbage collection occurs?
>> >> >
>> >> > I have a German windows version, so I can't tell you the exact
>> >> > name
>> >> > of
>> >> > the
>> >> > performance counter, should be something like "Number of GCs" in
>> >> > the
>> >> > ".NET
>> >> > Memory" performance counters section. It increases by one with
>> >> > each
>> >> > GC
>> >> > collection. Use perfmon to record it while you test your app.
>> >> >
>> >> >>> - Which GC do you use?
>> >> >>
>> >> >> How many are there? I thought there was just the one, built-in
>> >> >> to
>> >> >> the
>> >> >> framework.
>> >> >
>> >> > MSDN Quote: "The CLR has two different GCs: Workstation
>> >> > (mscorwks.dll)
>> >> > and
>> >> > Server (mscorsvr.dll). When running in Workstation mode, latency
>> >> > is
>> >> > more
>> >> > of a concern than space or efficiency. A server with multiple
>> >> > processors
>> >> > and clients connected over a network can afford some latency, but
>> >> > throughput is now a top priority. Rather than shoehorn both of
>> >> > these
>> >> > scenarios into a single GC scheme, Microsoft has included two
>> >> > garbage
>> >> > collectors that are tailored to each situation."
>> >> > [http://msdn.microsoft.com/library/de...perftechs.asp]
>> >> >
>> >> > You'll have to host the runtime to choose between the two, but I
>> >> > think
>> >> > the
>> >> > workstation version is the better choice for you anyway.
>> >> >
>> >> > Niki
>> >> >
>> >>
>> >>
>> >>
>>
>>
>>


Jul 21 '05 #37

P: n/a
CMM
> Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!
From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread for
any length of time."

I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to WorkerThread,
The New thread "queues" the call that will eventually occur on the UI thread.
Makes sense to me. ;-)

Having said that, I agree with your 80/20 characterization. It seems to me
that the chances of his bottleneck being the event model is low compared to
other possibilities.

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
when
BeginInvoke is called the framework has to spawn a thread momentarily in
order to return execution to the caller "immediately"

Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!

As long as you are not crossing an AppDomain my understanding is that no
real "marshalling" takes place either.

I would however expect the parameters to BeginInvoke to be "packaged" in an
"invoke" queue. This "invoke" queue could be the Win32 message queue, or it
could be a delegate & a parameters queue. This packaging in an invoke queue,
might not be any longer then your putting the information on a stack...

I would favor events due to the 80/20 rule, and I would use profiling to
identify if BeginInvoke was truly the bottleneck...

Remember that most programs follow the 80/20 rule (link below) that is 80%
of the execution time of your program is spent in 20% of your code. I will
optimize the 20% once that 20% has been identified & proven to be a
performance problem via profiling (see CLR Profiler in my other message).

For info on the 80/20 rule & optimizing only the 20% see Martin Fowler's
article "Yet Another Optimization Article" at
http://martinfowler.com/ieeeSoftware...timization.pdf

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:40**********************************@microsof t.com...
To clarify.... After thinking about it I realize that the timer model
might
have the same problems as the BeginInvoke model. However, it might still
alleviate the worker thread somewhat. Like I said... and AFAIK... when
BeginInvoke is called the framework has to spawn a thread momentarily in
order to return execution to the caller "immediately" before marshalling
the
call to the UI thread. This means that execution is not really really
returned to the caller "immediately." Why should the worker thread incur
this
expense? Let the UI thread deal with it (via the Timer).

Alas, in the end... I strongly suspect that your advice to use
EventArgs.Empty or *reuse* a custom eventargs object (with settable
properties) rather than reinstantiating a new one would (coupled with well
placed gc.Collects) help his problem more than any changes to his
Event/BeginInvoke technique.
"CMM" wrote:
I'd use the forms timer component as it's the best suited for this
purpose...
he's after all updating a form :-) ... set to some reasonable interval
that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's
doing-
is not without expense. A third thread has to be picked up from the pool
or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might
prove
detrimental to his worker thread. There's no guarantee that the work done
by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to
me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and
then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:

> CMM,
> What do you mean by "thread Timer"? Remember there are three timers in
> .NET.
>
> - System.Threading.Timer
> - System.Timers.Timer
> - System.Windows.Forms.Timer
>
> The first two you will need to use BeginInvoke either directly or
> indirectly, so I don't really see any potential "win" there. While the
> third
> will be on the UI thread.
>
> My point is in all three cases the UI thread will be exectuting code
> when it
> could simply wait for the BeginInvoke from the critical thread...
>
> Hope this helps
> Jay
>
>
> "CMM" <CM*@discussions.microsoft.com> wrote in message
> news:3B**********************************@microsof t.com...
> > You're probably right. But, I would think that a simple thread Timer
> > (rather
> > than a loop) in the UI is efficient enough to not steal CPU time from
> > the
> > worker thread... and it might (or not) be more efficient than the
> > event
> > model
> > / begininvoke he is using.
> >
> > "Jay B. Harlow [MVP - Outlook]" wrote:
> >
> >> CMM,
> >> Causing the UI thread to periodically check the status means that it
> >> would
> >> need to use CPU time that the critical thread may need, I would
> >> think
> >> Charles would want to minimize the amount of work other threads are
> >> using...
> >>
> >> Using BeginInvoke means the UI thread will only update the status
> >> when
> >> the
> >> critical thread made a change...
> >>
> >> Just a thought
> >> Jay
> >>
> >> "CMM" <CM*@discussions.microsoft.com> wrote in message
> >> news:97**********************************@microsof t.com...
> >> > If the culprit is the events perhaps you should rethink your
> >> > design...
> >> > and
> >> > use a shared or global variable to communicate state. The UI
> >> > thread
> >> > would
> >> > periodically check the status rather then the worker thread
> >> > informing
> >> > the
> >> > UI
> >> > via events.
> >> >
> >> > "Charles Law" wrote:
> >> >
> >> >> It's random in the sense that it doesn't always happen during the
> >> >> same
> >> >> operation, and sometimes it doesn't happen at all.
> >> >>
> >> >> The worker thread, repeatedly, does things like this:
> >> >>
> >> >> DoTask1
> >> >> DoTask2
> >> >> DoTask7
> >> >> DoTask2
> >> >>
> >> >> All these tasks have to be performed within a couple of seconds.
> >> >> Nominally,
> >> >> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms,
> >> >> say.
> >> >>
> >> >> The expectation, therefore, is that the whole process is over in
> >> >> less
> >> >> than 1
> >> >> second. Sometimes, though, task 1 takes 2.5 seconds, for no
> >> >> reason I
> >> >> can
> >> >> discern. Therefore, the entire sequence takes longer than the
> >> >> allowed
> >> >> time,
> >> >> and the process fails. That said, it is not always task 1 that
> >> >> takes
> >> >> the
> >> >> excess time; it could be task 2, or task 7, or task 43.
> >> >>
> >> >> Each of these tasks will send and receive data on a serial port.
> >> >> I
> >> >> have
> >> >> timed the serial comms carefully, and it consistently takes no
> >> >> more
> >> >> than
> >> >> 25
> >> >> ms to send and receive data. Thus, I conclude that the time is
> >> >> spent
> >> >> elsewhere.
> >> >>
> >> >> Before each task is started, an event is raised to inform the UI
> >> >> that
> >> >> the
> >> >> task is starting. The UI updates a rich text control using
> >> >> BeginInvoke. I
> >> >> am
> >> >> wondering if these requests to update the UI pile up, for
> >> >> example, and
> >> >> eventually get flushed, holding up the worker thread. The screen
> >> >> appears
> >> >> to
> >> >> update steadily, but by definition the screen updates will not be
> >> >> synchronised to the update requests, so some of them might result
> >> >> from
> >> >> the
> >> >> clearing of a backlog.
> >> >>
> >> >> When the UI displays the task being performed, I display the
> >> >> absolute
> >> >> time
> >> >> and the delta based on a high res counter.
> >> >>
> >> >> I will have a look at the performance counter you mention.
> >> >>
> >> >> Charles
> >> >>
> >> >>
> >> >> "Niki Estner" <ni*********@cube.net> wrote in message
> >> >> news:OW**************@TK2MSFTNGP12.phx.gbl...
> >> >> > "Charles Law" <bl***@nowhere.com> wrote in
> >> >> > news:up**************@TK2MSFTNGP10.phx.gbl...
> >> >> >> Hi Niki
> >> >> >>
> >> >> >> Thanks for the response. I currently display the absolute and
> >> >> >> elapsed
> >> >> >> times using a high res timer, which is how I can see the
> >> >> >> difference
> >> >> >> between the expected and actual timings. I guess I could add
> >> >> >> more
> >> >> >> time
> >> >> >> displays, but it would generate a lot of output, and whilst it
> >> >> >> might
> >> >> >> tell
> >> >> >> me when and where in my code the excess time is taken, I am
> >> >> >> not
> >> >> >> sure
> >> >> >> it
> >> >> >> will necessarily tell me why. I don't think it is my code
> >> >> >> (they all
> >> >> >> say
> >> >> >> that), because it is so random.
> >> >> >
> >> >> > Is it really random? How can you know without knowing where it
> >> >> > happens?
> >> >> > I
> >> >> > thought all you knew was that it doesn't happen every time?
> >> >> >
> >> >> > Did you analyze the time delta's? How are they distributed? Is
> >> >> > there
> >> >> > a
> >> >> > normal distribution around 300 ms plus some peaks at 2,5 s? If
> >> >> > so,
> >> >> > did
> >> >> > you
> >> >> > check where those peaks are? (I always dump output like that to
> >> >> > a
> >> >> > text
> >> >> > file and use Excel to analyze it later)
> >> >> >
> >> >> >>> - Monitor the .NET performance counters. Is there maybe some
> >> >> >>> correlation
> >> >> >>> to GC collection or some other runtime event?
> >> >> >>
> >> >> >> How can I tell when garbage collection occurs?
> >> >> >
> >> >> > I have a German windows version, so I can't tell you the exact
> >> >> > name
> >> >> > of
> >> >> > the
> >> >> > performance counter, should be something like "Number of GCs"
> >> >> > in the
> >> >> > ".NET
> >> >> > Memory" performance counters section. It increases by one with
> >> >> > each
> >> >> > GC
> >> >> > collection. Use perfmon to record it while you test your app.
> >> >> >
> >> >> >>> - Which GC do you use?
> >> >> >>
> >> >> >> How many are there? I thought there was just the one, built-in
> >> >> >> to
> >> >> >> the
> >> >> >> framework.
> >> >> >
> >> >> > MSDN Quote: "The CLR has two different GCs: Workstation
> >> >> > (mscorwks.dll)
> >> >> > and
> >> >> > Server (mscorsvr.dll). When running in Workstation mode,
> >> >> > latency is
> >> >> > more
> >> >> > of a concern than space or efficiency. A server with multiple
> >> >> > processors
> >> >> > and clients connected over a network can afford some latency,
> >> >> > but
> >> >> > throughput is now a top priority. Rather than shoehorn both of
> >> >> > these
> >> >> > scenarios into a single GC scheme, Microsoft has included two
> >> >> > garbage
> >> >> > collectors that are tailored to each situation."
> >> >> > [http://msdn.microsoft.com/library/de...perftechs.asp]
> >> >> >
> >> >> > You'll have to host the runtime to choose between the two, but
> >> >> > I
> >> >> > think
> >> >> > the
> >> >> > workstation version is the better choice for you anyway.
> >> >> >
> >> >> > Niki
> >> >> >
> >> >>
> >> >>
> >> >>
> >>
> >>
> >>
>
>
>


Jul 21 '05 #38

P: n/a
CMM
I tend to agree with all your comments...

But, now I'm all curious to find out if indeed Control.BeginInvoke doesn't
(momentarily) make use of a thread pool thread to queue up the delegate call.
I'm not saying that the call is carried out in the thread pool thread, only
that the actuall "queueing up" happens there. Could be that I was under the
wrong impression. Time to go churn out some play code... for edification! :-)

Regards.

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
Its seems that we are discussing the benefits of Polling over the benefits
on Events. In my experience Events are almost always better then polling!
Hence my comments... Yes polling may be better here, however I would use the
80

The "don't call us, we'll call you" pattern if you will. :-)

The fact that one object exists "in" a critical thread, while the second
object exists "in" the UI is largely immaterial. I would have the object
that exists in the critical object, simply raise one or more events to
notify others that something significant occured, then continually "pester"
it to see if it changed... Other objects such as the Form would handle these
events. In the case of worker thread & UI thread, a Form/Control on the UI
thread itself would use IsInvokeRequired to decide if the BeginInvoked
needed to be called or not.

Now because the "BeginInvoke" is encapsulated in the Form itself, if
profiling demonstrated that it was the bottle neck, then I can simply change
the form to use a Timer or other method to allow the critical thread to
notify the UI thread of changes...
In VS.NET 2005 (.NET 2.0 aka Whidbey, due out later in 2005) there is the
BackgroundWorker class that will simplify allowing a worker thread (object)
notify the UI thread (object) about "significant" events (progress changed &
completed). Basically a Mediator between the UI object/thread and the worker
object/thread...

http://msdn2.microsoft.com/library/4852et58.aspx

So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

??

I am referring to Control.BeginInvoke not Delegate.BeginInvoke, no threads
are created/taken & released from the thread pool!

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:98**********************************@microsof t.com...
I'd use the forms timer component as it's the best suited for this
purpose...
he's after all updating a form :-) ... set to some reasonable interval
that
makes sense in the context of a human looking at a screen.

BeginInvoke- especially calling it in such *quick succession* as he's
doing-
is not without expense. A third thread has to be picked up from the pool
or
created before the call is marshalled to the UI thread. Normally, nobody
cares and there's no noticeable performance impact.... but this might
prove
detrimental to his worker thread. There's no guarantee that the work done
by
the delegate called via the previous BeginInvoke is finished before
BeginInvoke is called again. So, the calls "build up", threads are
created/taken and then released from the pool, all in a blink of an eye.

That can't be good for his worker thread. I don't know. It just seems to
me
that a "time critical" thread shouldn't have to worry in any way about
notifying other threads of status. Fill a stack, forget about it, and then
whoever is interested in your status can look it up.
"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
What do you mean by "thread Timer"? Remember there are three timers in
.NET.

- System.Threading.Timer
- System.Timers.Timer
- System.Windows.Forms.Timer

The first two you will need to use BeginInvoke either directly or
indirectly, so I don't really see any potential "win" there. While the
third
will be on the UI thread.

My point is in all three cases the UI thread will be exectuting code when
it
could simply wait for the BeginInvoke from the critical thread...

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:3B**********************************@microsof t.com...
> You're probably right. But, I would think that a simple thread Timer
> (rather
> than a loop) in the UI is efficient enough to not steal CPU time from
> the
> worker thread... and it might (or not) be more efficient than the event
> model
> / begininvoke he is using.
>
> "Jay B. Harlow [MVP - Outlook]" wrote:
>
>> CMM,
>> Causing the UI thread to periodically check the status means that it
>> would
>> need to use CPU time that the critical thread may need, I would think
>> Charles would want to minimize the amount of work other threads are
>> using...
>>
>> Using BeginInvoke means the UI thread will only update the status when
>> the
>> critical thread made a change...
>>
>> Just a thought
>> Jay
>>
>> "CMM" <CM*@discussions.microsoft.com> wrote in message
>> news:97**********************************@microsof t.com...
>> > If the culprit is the events perhaps you should rethink your
>> > design...
>> > and
>> > use a shared or global variable to communicate state. The UI thread
>> > would
>> > periodically check the status rather then the worker thread
>> > informing
>> > the
>> > UI
>> > via events.
>> >
>> > "Charles Law" wrote:
>> >
>> >> It's random in the sense that it doesn't always happen during the
>> >> same
>> >> operation, and sometimes it doesn't happen at all.
>> >>
>> >> The worker thread, repeatedly, does things like this:
>> >>
>> >> DoTask1
>> >> DoTask2
>> >> DoTask7
>> >> DoTask2
>> >>
>> >> All these tasks have to be performed within a couple of seconds.
>> >> Nominally,
>> >> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms,
>> >> say.
>> >>
>> >> The expectation, therefore, is that the whole process is over in
>> >> less
>> >> than 1
>> >> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason
>> >> I
>> >> can
>> >> discern. Therefore, the entire sequence takes longer than the
>> >> allowed
>> >> time,
>> >> and the process fails. That said, it is not always task 1 that
>> >> takes
>> >> the
>> >> excess time; it could be task 2, or task 7, or task 43.
>> >>
>> >> Each of these tasks will send and receive data on a serial port. I
>> >> have
>> >> timed the serial comms carefully, and it consistently takes no more
>> >> than
>> >> 25
>> >> ms to send and receive data. Thus, I conclude that the time is
>> >> spent
>> >> elsewhere.
>> >>
>> >> Before each task is started, an event is raised to inform the UI
>> >> that
>> >> the
>> >> task is starting. The UI updates a rich text control using
>> >> BeginInvoke. I
>> >> am
>> >> wondering if these requests to update the UI pile up, for example,
>> >> and
>> >> eventually get flushed, holding up the worker thread. The screen
>> >> appears
>> >> to
>> >> update steadily, but by definition the screen updates will not be
>> >> synchronised to the update requests, so some of them might result
>> >> from
>> >> the
>> >> clearing of a backlog.
>> >>
>> >> When the UI displays the task being performed, I display the
>> >> absolute
>> >> time
>> >> and the delta based on a high res counter.
>> >>
>> >> I will have a look at the performance counter you mention.
>> >>
>> >> Charles
>> >>
>> >>
>> >> "Niki Estner" <ni*********@cube.net> wrote in message
>> >> news:OW**************@TK2MSFTNGP12.phx.gbl...
>> >> > "Charles Law" <bl***@nowhere.com> wrote in
>> >> > news:up**************@TK2MSFTNGP10.phx.gbl...
>> >> >> Hi Niki
>> >> >>
>> >> >> Thanks for the response. I currently display the absolute and
>> >> >> elapsed
>> >> >> times using a high res timer, which is how I can see the
>> >> >> difference
>> >> >> between the expected and actual timings. I guess I could add
>> >> >> more
>> >> >> time
>> >> >> displays, but it would generate a lot of output, and whilst it
>> >> >> might
>> >> >> tell
>> >> >> me when and where in my code the excess time is taken, I am not
>> >> >> sure
>> >> >> it
>> >> >> will necessarily tell me why. I don't think it is my code (they
>> >> >> all
>> >> >> say
>> >> >> that), because it is so random.
>> >> >
>> >> > Is it really random? How can you know without knowing where it
>> >> > happens?
>> >> > I
>> >> > thought all you knew was that it doesn't happen every time?
>> >> >
>> >> > Did you analyze the time delta's? How are they distributed? Is
>> >> > there
>> >> > a
>> >> > normal distribution around 300 ms plus some peaks at 2,5 s? If
>> >> > so,
>> >> > did
>> >> > you
>> >> > check where those peaks are? (I always dump output like that to a
>> >> > text
>> >> > file and use Excel to analyze it later)
>> >> >
>> >> >>> - Monitor the .NET performance counters. Is there maybe some
>> >> >>> correlation
>> >> >>> to GC collection or some other runtime event?
>> >> >>
>> >> >> How can I tell when garbage collection occurs?
>> >> >
>> >> > I have a German windows version, so I can't tell you the exact
>> >> > name
>> >> > of
>> >> > the
>> >> > performance counter, should be something like "Number of GCs" in
>> >> > the
>> >> > ".NET
>> >> > Memory" performance counters section. It increases by one with
>> >> > each
>> >> > GC
>> >> > collection. Use perfmon to record it while you test your app.
>> >> >
>> >> >>> - Which GC do you use?
>> >> >>
>> >> >> How many are there? I thought there was just the one, built-in
>> >> >> to
>> >> >> the
>> >> >> framework.
>> >> >
>> >> > MSDN Quote: "The CLR has two different GCs: Workstation
>> >> > (mscorwks.dll)
>> >> > and
>> >> > Server (mscorsvr.dll). When running in Workstation mode, latency
>> >> > is
>> >> > more
>> >> > of a concern than space or efficiency. A server with multiple
>> >> > processors
>> >> > and clients connected over a network can afford some latency, but
>> >> > throughput is now a top priority. Rather than shoehorn both of
>> >> > these
>> >> > scenarios into a single GC scheme, Microsoft has included two
>> >> > garbage
>> >> > collectors that are tailored to each situation."
>> >> > [http://msdn.microsoft.com/library/de...perftechs.asp]
>> >> >
>> >> > You'll have to host the runtime to choose between the two, but I
>> >> > think
>> >> > the
>> >> > workstation version is the better choice for you anyway.
>> >> >
>> >> > Niki
>> >> >
>> >>
>> >>
>> >>
>>
>>
>>


Jul 21 '05 #39

P: n/a
I see what you mean with the stack idea. It's a bit like the way BeginInvoke
would work though, in that the worker thread appends strings to the rich
text control, and the UI thread removes them, asynchronously, and puts them
on the screen. The difference being, perhaps, that I could have more control
over when it all happens.

As far as the rtf goes, there are actually several events raised. When all
is well a Feedback event is raised, and the string passed is placed in the
rich text control unchanged. When a failure occurs, a different event is
raised, and the UI handler that sinks this puts the string into the rich
text control with a fore colour of red.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F1**********************************@microsof t.com...
The worker thread can push "states" into a stack collection. The UI thread
can pop states out. You'd use the SyncLock mechanism (VB parlance) to
allow
for both threads to access the collection. The UI thread would NOT
enumerate
the collection and fill the rich text box at the same time (which might be
an
expensive process)... that's dumb... rather it would pop out the states
and
collect them itself and then fill the textbox on its own time so as to
leave
the stack collection alone as quickly as possible.

Your RTF thing confused me... is the worker thread sending back RTF
strings?
Why? And if so, why can't you just store those same strings in a regular
ol'
collection?

Just an idea.

"Charles Law" wrote:
The status is accumulated in the rich text box, so just checking it
periodically would mean that some state changes could be missed. The rich
text box needs to keep a history of all states, as notified by the worker
thread.

One thought I had was to accumulate the state in-memory, which would
undoubtedly be quicker than updating the screen all the time. The problem
I
can see with that is that I don't have an in-memory class that can
interpret
rtf codes, such as the ones that are embedded in the rich text control to
show failed processes in red.

Do you know of a class that can process/manipulate rtf w/o rendering it?

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:97**********************************@microsof t.com...
> If the culprit is the events perhaps you should rethink your design...
> and
> use a shared or global variable to communicate state. The UI thread
> would
> periodically check the status rather then the worker thread informing
> the
> UI
> via events.
>
> "Charles Law" wrote:
>
>> It's random in the sense that it doesn't always happen during the same
>> operation, and sometimes it doesn't happen at all.
>>
>> The worker thread, repeatedly, does things like this:
>>
>> DoTask1
>> DoTask2
>> DoTask7
>> DoTask2
>>
>> All these tasks have to be performed within a couple of seconds.
>> Nominally,
>> task1 takes 60 ms, task 2 takes 10 ms, and task 7 takes 550 ms, say.
>>
>> The expectation, therefore, is that the whole process is over in less
>> than 1
>> second. Sometimes, though, task 1 takes 2.5 seconds, for no reason I
>> can
>> discern. Therefore, the entire sequence takes longer than the allowed
>> time,
>> and the process fails. That said, it is not always task 1 that takes
>> the
>> excess time; it could be task 2, or task 7, or task 43.
>>
>> Each of these tasks will send and receive data on a serial port. I
>> have
>> timed the serial comms carefully, and it consistently takes no more
>> than
>> 25
>> ms to send and receive data. Thus, I conclude that the time is spent
>> elsewhere.
>>
>> Before each task is started, an event is raised to inform the UI that
>> the
>> task is starting. The UI updates a rich text control using
>> BeginInvoke. I
>> am
>> wondering if these requests to update the UI pile up, for example, and
>> eventually get flushed, holding up the worker thread. The screen
>> appears
>> to
>> update steadily, but by definition the screen updates will not be
>> synchronised to the update requests, so some of them might result from
>> the
>> clearing of a backlog.
>>
>> When the UI displays the task being performed, I display the absolute
>> time
>> and the delta based on a high res counter.
>>
>> I will have a look at the performance counter you mention.
>>
>> Charles
>>
>>
>> "Niki Estner" <ni*********@cube.net> wrote in message
>> news:OW**************@TK2MSFTNGP12.phx.gbl...
>> > "Charles Law" <bl***@nowhere.com> wrote in
>> > news:up**************@TK2MSFTNGP10.phx.gbl...
>> >> Hi Niki
>> >>
>> >> Thanks for the response. I currently display the absolute and
>> >> elapsed
>> >> times using a high res timer, which is how I can see the difference
>> >> between the expected and actual timings. I guess I could add more
>> >> time
>> >> displays, but it would generate a lot of output, and whilst it
>> >> might
>> >> tell
>> >> me when and where in my code the excess time is taken, I am not
>> >> sure
>> >> it
>> >> will necessarily tell me why. I don't think it is my code (they all
>> >> say
>> >> that), because it is so random.
>> >
>> > Is it really random? How can you know without knowing where it
>> > happens?
>> > I
>> > thought all you knew was that it doesn't happen every time?
>> >
>> > Did you analyze the time delta's? How are they distributed? Is there
>> > a
>> > normal distribution around 300 ms plus some peaks at 2,5 s? If so,
>> > did
>> > you
>> > check where those peaks are? (I always dump output like that to a
>> > text
>> > file and use Excel to analyze it later)
>> >
>> >>> - Monitor the .NET performance counters. Is there maybe some
>> >>> correlation
>> >>> to GC collection or some other runtime event?
>> >>
>> >> How can I tell when garbage collection occurs?
>> >
>> > I have a German windows version, so I can't tell you the exact name
>> > of
>> > the
>> > performance counter, should be something like "Number of GCs" in the
>> > ".NET
>> > Memory" performance counters section. It increases by one with each
>> > GC
>> > collection. Use perfmon to record it while you test your app.
>> >
>> >>> - Which GC do you use?
>> >>
>> >> How many are there? I thought there was just the one, built-in to
>> >> the
>> >> framework.
>> >
>> > MSDN Quote: "The CLR has two different GCs: Workstation
>> > (mscorwks.dll)
>> > and
>> > Server (mscorsvr.dll). When running in Workstation mode, latency is
>> > more
>> > of a concern than space or efficiency. A server with multiple
>> > processors
>> > and clients connected over a network can afford some latency, but
>> > throughput is now a top priority. Rather than shoehorn both of these
>> > scenarios into a single GC scheme, Microsoft has included two
>> > garbage
>> > collectors that are tailored to each situation."
>> > [http://msdn.microsoft.com/library/de...perftechs.asp]
>> >
>> > You'll have to host the runtime to choose between the two, but I
>> > think
>> > the
>> > workstation version is the better choice for you anyway.
>> >
>> > Niki
>> >
>>
>>
>>


Jul 21 '05 #40

P: n/a
I am wading through it all now :-)

There are about 30 classes that can raise events, each with their own custom
EventArgs class. At the moment I use New each time I raise an event. I
should add that each task in my critical process does not use 30 classes.
Each task uses just one of any of these 30 class objects. The class objects
are pre-loaded, and are not therefore created on-the-fly.

Incidentally, I used PerfMon to look at what was happening with the GC, and
when I added a GC.Collect into one of my tasks, I saw the % time in GC value
increase. Weird, but not entirely unexpected?

Cheers.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:u2**************@TK2MSFTNGP12.phx.gbl...
Charles,
Once you rule out other apps (NAV, Screen Savers), which you cannot really
do anything real about anyway (process priority may help, a little). CMM &
my suggestions of redesigning the critical part is what you will need to
do.

If you decide to use GC.Collect be certain to read & adhere to Rule #1 at:

http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx
The following links may (or may not) help in the redesign:
http://blogs.msdn.com/ricom/

http://blogs.msdn.com/maoni/

(the above two blogs have a number of useful articles, check all the
articles).

http://msdn.microsoft.com/library/de...anagedapps.asp
http://blogs.msdn.com/junfeng/archiv...13/181534.aspx

I would consider recoding the critical thread in C++ if profiling proved
that the GC & managed code was the problem...

What parameters are on your events? I normally use EventArgs.Empty instead
of New EventArgs. If you have a custom EventArgs class, I would consider
making it read write & reusing a single instance for all events that may
be raised by the critical code. Assuming that the GC is the problem...

I thought CLR Profiling will identify if your critical code itself is
taking all the time or if another thread is getting all the time. In other
words when you critical thread takes 2.5 seconds, how much of that CPU
time did your critical thread get & how much did other threads get...

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:eO**************@tk2msftngp13.phx.gbl...
There are certainly points in my process where I could perform a garbage
collect w/o upsetting the timing, so I will try a gc.Collect there and
see what happens.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C3**********************************@microsof t.com...
1) Force a garbage collection when it won't interfere with your time
sensitive loop... using gc.Collect().
2) Use structures. These get allocated and deallocated on demand.
3) Reuse objects where possible rather than reinstantiating new ones.
Perhaps using some sort of object pool or something.

Hopefully someone here might have some more robust "hardcore" ways to
help.
The following article might help too...
-
http://msdn.microsoft.com/library/de...etgcbasics.asp
- http://msdn.microsoft.com/msdnmag/is...2/default.aspx

"Charles Law" wrote:

> 1) Run the application in release mode. Applications with debug
> symbol
> baggage tend to run slower.

It is currently running that way.

> 2) Boost the priority of the thread.

Currently set to AboveNormal.

> 3) I'm not sure if this is redundant with #2 but you can try
> increasing
> the
> application's priority. Via Task Manager, select the process and
> select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.

Not tried, but I am inclined to agree with you assessment.

> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.

Each task in the process is in a Try .. Catch block, and any exception
would
appear on screen. In this case I do not get any exception reported.

> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting
> ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.

The data in these tasks are pretty constant, so I would expect the
exceptions to be constant too, if there are any. The extra time does
not
always appear in the same place (or at all), but the data do not
change.

>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type
> objects?).

This is certainly one of my concerns, but I am unsure how I can
restrict
garbage collection to non-time sensitive areas of my code. And yes, I
am
creating a lot of non-value types; mostly associated with the raising
of
events.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:F3**********************************@microsof t.com...
> 1) Run the application in release mode. Applications with debug
> symbol
> baggage tend to run slower.
> 2) Boost the priority of the thread.
> 3) I'm not sure if this is redundant with #2 but you can try
> increasing
> the
> application's priority. Via Task Manager, select the process and
> select
> "Set
> Priority." I'm sure there's a way to do this via the framework or at
> least
> a
> Win32 API as well.
> 4) Make sure the slowdown isn't caused by exceptions (even if handled
> in
> your worker thread). Exceptions will halt the thread as the framework
> processes it.
> 5) Similarly to #3... be aware that some methods may throw and handle
> their
> own exceptions... all transparent to the caller. This will still slow
> everything down even though you never get the exception. You might be
> able
> to
> find the offending method by going to Debug|Exceptions and setting
> ALL
> exceptions to 'Break into Debugger' regardless if the exception is
> handled.
>
> In the end, after all is said and done, it might be due to garbage
> collection. Garbage collection will pause your app momentarily. There
> are
> tricks to minimize this and effective object management and pooling
> helps
> (are you instantiating and releasing a lot of non-value type
> objects?).
>
>
> "Charles Law" wrote:
>
>> Hi guys
>>
>> I have a time critical process, running on a worker thread. By "time
>> critical", I mean that certain parts of the process must be
>> completed in
>> a
>> specific time frame. The time when the process starts is not
>> especially
>> important, but it must be complete within a small number of seconds.
>>
>> The operations I am performing do not take a long time (hundreds of
>> milliseconds), but as each part of the process is complete, my
>> worker
>> thread
>> raises an event that is handled by the UI thread, to update a rich
>> text
>> control with details of the completed operation. I am using a rich
>> text
>> box
>> so that when a failure occurs I can colour the message red.
>>
>> The problem I have is that sometimes, for no apparent reason, a step
>> in
>> my
>> process takes an inordinate amount of time, e.g 2.5 seconds instead
>> of
>> perhaps 300 ms. When this happens, the complete process overruns my
>> time
>> frame, and it has to be repeated. When I repeat the process there is
>> every
>> chance that it completes in a realistic time, and all is well. If I
>> stop
>> outputting to the screen, I do not get the problem.
>>
>> When updating the screen on the UI thread, I use BeginInvoke, to
>> marshal
>> the
>> operation to the correct thread, and so as not to hold up the worker
>> thread,
>> but this does not seem to help.
>>
>> I realise that Windows (XP in this case) is not the ideal o/s for
>> this
>> type
>> of application, but does anyone have any ideas about how I could
>> make my
>> application more deterministic? I am not certain what is going on in
>> these
>> 2.5 seconds, so it might be useful if I could find out, but I am not
>> sure
>> how I would do that.
>>
>> TIA
>>
>> Charles
>>
>>
>>



Jul 21 '05 #41

P: n/a
Charles,

Sometimes starting completely new (for the problem part of course) will give
a huge amount of time wining. The only problem is that you can only say that
afterwards when you did not do that.

Just a thought in with I wanted you to deal.

Cor
Jul 21 '05 #42

P: n/a
CMM <CM*@discussions.microsoft.com> wrote:
Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!
From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread for
any length of time."


Yes, that's just a bug in the documentation though. I reported it to MS
a while ago - hopefully it'll be fixed by the time .NET 2.0 ships.
I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to WorkerThread,
The New thread "queues" the call that will eventually occur on the UI thread.
Makes sense to me. ;-)


Unlikely, IMO. I suspect it's more likely that it uses a Win32
PostMessage or something similar. I don't see any reason to get an
extra thread involved.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too
Jul 21 '05 #43

P: n/a
CMM,
From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time." IMHO that sounds like a serious documentation error! I will check with MS to
make sure. I would expect the paragraph to read something like: "Note The
BeginInvoke method calls the specified delegate back on the control's UI
thread. You should not block the control's UI thread for any length of
time."

The first paragraph is the important one. "Executes the specified delegate
asynchronously on the thread that the control's underlying handle was
created on."

Think very carefully about it. If the purpose of Control.BeginInvoke is to
"execute on the thread that the control was created on", why would a third
thread from the thread pool be involved? Ergo the statement you quoted is
highly suspect and I will check with MS on it!
I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Sounds like you are double queuing the request, which IMHO is one queuing
too many. In other words it makes more sense when the worker thread calls
BeginInvoke, BeginInvoke simply queues the request for the main thread to
execute it. Rather then have the worker thread, queue a request for the
thread pool, then the thread pool simply queues the request for the UI
thread.

I don't have the Rotor source loaded, however using ILDASM & Rotor,
Control.BeginInvoke calls Control.MarshaledInvoke, which registers a private
windows message and calls the win32 GetWindowThreadProcessId & PostMessage
APIs. I don't see any reference to the Thread Pool in the implementation of
Control.BeginInvoke...

I will post something to MS about the documentation...

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C2**********************************@microsof t.com...
Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!


From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."

I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Having said that, I agree with your 80/20 characterization. It seems to me
that the chances of his bottleneck being the event model is low compared
to
other possibilities.

<<snip>>
Jul 21 '05 #44

P: n/a
Jon,
Yes, that's just a bug in the documentation though. I reported it to MS
a while ago - hopefully it'll be fixed by the time .NET 2.0 ships. I was just noticed that .NET 2.0 beta docs currently contains the same bug.

http://msdn2.microsoft.com/library/0b1bf3y3.aspx

If you already submitted a bug report on it, I don't think I need to...

Thanks
Jay
"Jon Skeet [C# MVP]" <sk***@pobox.com> wrote in message
news:MP************************@msnews.microsoft.c om... CMM <CM*@discussions.microsoft.com> wrote:
> Control.BeginInvoke does not "spawn a thread", it sounds like you are
> thinking Delegate.BeginInvoke which needs to "spawn a thread"!


From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."


Yes, that's just a bug in the documentation though. I reported it to MS
a while ago - hopefully it'll be fixed by the time .NET 2.0 ships.
I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke,
BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)


Unlikely, IMO. I suspect it's more likely that it uses a Win32
PostMessage or something similar. I don't see any reason to get an
extra thread involved.

--
Jon Skeet - <sk***@pobox.com>
http://www.pobox.com/~skeet
If replying to the group, please do not mail me too

Jul 21 '05 #45

P: n/a
Charles,
There are about 30 classes that can raise events, each with their own
custom During the critical thread how many custom EventArgs & other objects are you
creating?
Incidentally, I used PerfMon to look at what was happening with the GC,
and when I added a GC.Collect into one of my tasks, I saw the % time in GC
value increase. Weird, but not entirely unexpected? Yes calling GC.Collect will cause the GC to behave "badly", for details see
Rule #1 at:
http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx


You may want to use CLR Profiler instead of PerfMon to get a better feel of
what is happening with your objects during the critical thread.
Unfortunately I have not used CLR Profiler enough to get a good idea of how
to use it only for the critical thread section of your code...

Hope this helps
Jay
"Charles Law" <bl***@nowhere.com> wrote in message
news:eV**************@TK2MSFTNGP15.phx.gbl...I am wading through it all now :-)

There are about 30 classes that can raise events, each with their own
custom EventArgs class. At the moment I use New each time I raise an
event. I should add that each task in my critical process does not use 30
classes. Each task uses just one of any of these 30 class objects. The
class objects are pre-loaded, and are not therefore created on-the-fly.

Incidentally, I used PerfMon to look at what was happening with the GC,
and when I added a GC.Collect into one of my tasks, I saw the % time in GC
value increase. Weird, but not entirely unexpected?

Cheers.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:u2**************@TK2MSFTNGP12.phx.gbl...
Charles,
Once you rule out other apps (NAV, Screen Savers), which you cannot
really do anything real about anyway (process priority may help, a
little). CMM & my suggestions of redesigning the critical part is what
you will need to do.

If you decide to use GC.Collect be certain to read & adhere to Rule #1
at:

http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx
The following links may (or may not) help in the redesign:
http://blogs.msdn.com/ricom/

http://blogs.msdn.com/maoni/

(the above two blogs have a number of useful articles, check all the
articles).

http://msdn.microsoft.com/library/de...anagedapps.asp
http://blogs.msdn.com/junfeng/archiv...13/181534.aspx

I would consider recoding the critical thread in C++ if profiling proved
that the GC & managed code was the problem...

What parameters are on your events? I normally use EventArgs.Empty
instead of New EventArgs. If you have a custom EventArgs class, I would
consider making it read write & reusing a single instance for all events
that may be raised by the critical code. Assuming that the GC is the
problem...

I thought CLR Profiling will identify if your critical code itself is
taking all the time or if another thread is getting all the time. In
other words when you critical thread takes 2.5 seconds, how much of that
CPU time did your critical thread get & how much did other threads get...

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:eO**************@tk2msftngp13.phx.gbl...
There are certainly points in my process where I could perform a garbage
collect w/o upsetting the timing, so I will try a gc.Collect there and
see what happens.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C3**********************************@microsof t.com...
1) Force a garbage collection when it won't interfere with your time
sensitive loop... using gc.Collect().
2) Use structures. These get allocated and deallocated on demand.
3) Reuse objects where possible rather than reinstantiating new ones.
Perhaps using some sort of object pool or something.

Hopefully someone here might have some more robust "hardcore" ways to
help.
The following article might help too...
-
http://msdn.microsoft.com/library/de...etgcbasics.asp
- http://msdn.microsoft.com/msdnmag/is...2/default.aspx

"Charles Law" wrote:

> > 1) Run the application in release mode. Applications with debug
> > symbol
> > baggage tend to run slower.
>
> It is currently running that way.
>
> > 2) Boost the priority of the thread.
>
> Currently set to AboveNormal.
>
> > 3) I'm not sure if this is redundant with #2 but you can try
> > increasing
> > the
> > application's priority. Via Task Manager, select the process and
> > select
> > "Set
> > Priority." I'm sure there's a way to do this via the framework or at
> > least
> > a
> > Win32 API as well.
>
> Not tried, but I am inclined to agree with you assessment.
>
> > 4) Make sure the slowdown isn't caused by exceptions (even if
> > handled in
> > your worker thread). Exceptions will halt the thread as the
> > framework
> > processes it.
>
> Each task in the process is in a Try .. Catch block, and any exception
> would
> appear on screen. In this case I do not get any exception reported.
>
> > 5) Similarly to #3... be aware that some methods may throw and
> > handle
> > their
> > own exceptions... all transparent to the caller. This will still
> > slow
> > everything down even though you never get the exception. You might
> > be able
> > to
> > find the offending method by going to Debug|Exceptions and setting
> > ALL
> > exceptions to 'Break into Debugger' regardless if the exception is
> > handled.
>
> The data in these tasks are pretty constant, so I would expect the
> exceptions to be constant too, if there are any. The extra time does
> not
> always appear in the same place (or at all), but the data do not
> change.
>
> >
> > In the end, after all is said and done, it might be due to garbage
> > collection. Garbage collection will pause your app momentarily.
> > There are
> > tricks to minimize this and effective object management and pooling
> > helps
> > (are you instantiating and releasing a lot of non-value type
> > objects?).
>
> This is certainly one of my concerns, but I am unsure how I can
> restrict
> garbage collection to non-time sensitive areas of my code. And yes, I
> am
> creating a lot of non-value types; mostly associated with the raising
> of
> events.
>
> Charles
>
>
> "CMM" <CM*@discussions.microsoft.com> wrote in message
> news:F3**********************************@microsof t.com...
> > 1) Run the application in release mode. Applications with debug
> > symbol
> > baggage tend to run slower.
> > 2) Boost the priority of the thread.
> > 3) I'm not sure if this is redundant with #2 but you can try
> > increasing
> > the
> > application's priority. Via Task Manager, select the process and
> > select
> > "Set
> > Priority." I'm sure there's a way to do this via the framework or at
> > least
> > a
> > Win32 API as well.
> > 4) Make sure the slowdown isn't caused by exceptions (even if
> > handled in
> > your worker thread). Exceptions will halt the thread as the
> > framework
> > processes it.
> > 5) Similarly to #3... be aware that some methods may throw and
> > handle
> > their
> > own exceptions... all transparent to the caller. This will still
> > slow
> > everything down even though you never get the exception. You might
> > be able
> > to
> > find the offending method by going to Debug|Exceptions and setting
> > ALL
> > exceptions to 'Break into Debugger' regardless if the exception is
> > handled.
> >
> > In the end, after all is said and done, it might be due to garbage
> > collection. Garbage collection will pause your app momentarily.
> > There are
> > tricks to minimize this and effective object management and pooling
> > helps
> > (are you instantiating and releasing a lot of non-value type
> > objects?).
> >
> >
> > "Charles Law" wrote:
> >
> >> Hi guys
> >>
> >> I have a time critical process, running on a worker thread. By
> >> "time
> >> critical", I mean that certain parts of the process must be
> >> completed in
> >> a
> >> specific time frame. The time when the process starts is not
> >> especially
> >> important, but it must be complete within a small number of
> >> seconds.
> >>
> >> The operations I am performing do not take a long time (hundreds of
> >> milliseconds), but as each part of the process is complete, my
> >> worker
> >> thread
> >> raises an event that is handled by the UI thread, to update a rich
> >> text
> >> control with details of the completed operation. I am using a rich
> >> text
> >> box
> >> so that when a failure occurs I can colour the message red.
> >>
> >> The problem I have is that sometimes, for no apparent reason, a
> >> step in
> >> my
> >> process takes an inordinate amount of time, e.g 2.5 seconds instead
> >> of
> >> perhaps 300 ms. When this happens, the complete process overruns my
> >> time
> >> frame, and it has to be repeated. When I repeat the process there
> >> is
> >> every
> >> chance that it completes in a realistic time, and all is well. If I
> >> stop
> >> outputting to the screen, I do not get the problem.
> >>
> >> When updating the screen on the UI thread, I use BeginInvoke, to
> >> marshal
> >> the
> >> operation to the correct thread, and so as not to hold up the
> >> worker
> >> thread,
> >> but this does not seem to help.
> >>
> >> I realise that Windows (XP in this case) is not the ideal o/s for
> >> this
> >> type
> >> of application, but does anyone have any ideas about how I could
> >> make my
> >> application more deterministic? I am not certain what is going on
> >> in
> >> these
> >> 2.5 seconds, so it might be useful if I could find out, but I am
> >> not sure
> >> how I would do that.
> >>
> >> TIA
> >>
> >> Charles
> >>
> >>
> >>
>
>
>



Jul 21 '05 #46

P: n/a
CMM
Post any responses from MS to the group. Interesting topic. G'luck!

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."

IMHO that sounds like a serious documentation error! I will check with MS to
make sure. I would expect the paragraph to read something like: "Note The
BeginInvoke method calls the specified delegate back on the control's UI
thread. You should not block the control's UI thread for any length of
time."

The first paragraph is the important one. "Executes the specified delegate
asynchronously on the thread that the control's underlying handle was
created on."

Think very carefully about it. If the purpose of Control.BeginInvoke is to
"execute on the thread that the control was created on", why would a third
thread from the thread pool be involved? Ergo the statement you quoted is
highly suspect and I will check with MS on it!
I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Sounds like you are double queuing the request, which IMHO is one queuing
too many. In other words it makes more sense when the worker thread calls
BeginInvoke, BeginInvoke simply queues the request for the main thread to
execute it. Rather then have the worker thread, queue a request for the
thread pool, then the thread pool simply queues the request for the UI
thread.

I don't have the Rotor source loaded, however using ILDASM & Rotor,
Control.BeginInvoke calls Control.MarshaledInvoke, which registers a private
windows message and calls the win32 GetWindowThreadProcessId & PostMessage
APIs. I don't see any reference to the Thread Pool in the implementation of
Control.BeginInvoke...

I will post something to MS about the documentation...

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C2**********************************@microsof t.com...
Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!


From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."

I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Having said that, I agree with your 80/20 characterization. It seems to me
that the chances of his bottleneck being the event model is low compared
to
other possibilities.

<<snip>>

Jul 21 '05 #47

P: n/a
I probably create about five custom EventArgs for each task. Although there
is only one directly per task, the associated processes generate several
more. That said, there are no handlers sinking the events raised by these
associated processes, so the custom EventArgs will not, in most cases, be
created.

I'll have a look at the CLR profiler, and see if I can get it to do what
PerfMon was doing.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:uk**************@TK2MSFTNGP14.phx.gbl...
Charles,
There are about 30 classes that can raise events, each with their own
custom

During the critical thread how many custom EventArgs & other objects are
you creating?
Incidentally, I used PerfMon to look at what was happening with the GC,
and when I added a GC.Collect into one of my tasks, I saw the % time in
GC value increase. Weird, but not entirely unexpected?

Yes calling GC.Collect will cause the GC to behave "badly", for details
see Rule #1 at:
http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx


You may want to use CLR Profiler instead of PerfMon to get a better feel
of what is happening with your objects during the critical thread.
Unfortunately I have not used CLR Profiler enough to get a good idea of
how to use it only for the critical thread section of your code...

Hope this helps
Jay
"Charles Law" <bl***@nowhere.com> wrote in message
news:eV**************@TK2MSFTNGP15.phx.gbl...
I am wading through it all now :-)

There are about 30 classes that can raise events, each with their own
custom EventArgs class. At the moment I use New each time I raise an
event. I should add that each task in my critical process does not use 30
classes. Each task uses just one of any of these 30 class objects. The
class objects are pre-loaded, and are not therefore created on-the-fly.

Incidentally, I used PerfMon to look at what was happening with the GC,
and when I added a GC.Collect into one of my tasks, I saw the % time in
GC value increase. Weird, but not entirely unexpected?

Cheers.

Charles
"Jay B. Harlow [MVP - Outlook]" <Ja************@msn.com> wrote in message
news:u2**************@TK2MSFTNGP12.phx.gbl...
Charles,
Once you rule out other apps (NAV, Screen Savers), which you cannot
really do anything real about anyway (process priority may help, a
little). CMM & my suggestions of redesigning the critical part is what
you will need to do.

If you decide to use GC.Collect be certain to read & adhere to Rule #1
at:

http://blogs.msdn.com/ricom/archive/...29/271829.aspx
http://blogs.msdn.com/ricom/archive/.../02/40780.aspx
The following links may (or may not) help in the redesign:
http://blogs.msdn.com/ricom/

http://blogs.msdn.com/maoni/

(the above two blogs have a number of useful articles, check all the
articles).

http://msdn.microsoft.com/library/de...anagedapps.asp
http://blogs.msdn.com/junfeng/archiv...13/181534.aspx

I would consider recoding the critical thread in C++ if profiling proved
that the GC & managed code was the problem...

What parameters are on your events? I normally use EventArgs.Empty
instead of New EventArgs. If you have a custom EventArgs class, I would
consider making it read write & reusing a single instance for all events
that may be raised by the critical code. Assuming that the GC is the
problem...

I thought CLR Profiling will identify if your critical code itself is
taking all the time or if another thread is getting all the time. In
other words when you critical thread takes 2.5 seconds, how much of that
CPU time did your critical thread get & how much did other threads
get...

Hope this helps
Jay

"Charles Law" <bl***@nowhere.com> wrote in message
news:eO**************@tk2msftngp13.phx.gbl...
There are certainly points in my process where I could perform a
garbage collect w/o upsetting the timing, so I will try a gc.Collect
there and see what happens.

Charles
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C3**********************************@microsof t.com...
> 1) Force a garbage collection when it won't interfere with your time
> sensitive loop... using gc.Collect().
> 2) Use structures. These get allocated and deallocated on demand.
> 3) Reuse objects where possible rather than reinstantiating new ones.
> Perhaps using some sort of object pool or something.
>
> Hopefully someone here might have some more robust "hardcore" ways to
> help.
> The following article might help too...
> -
> http://msdn.microsoft.com/library/de...etgcbasics.asp
> - http://msdn.microsoft.com/msdnmag/is...2/default.aspx
>
>
>
> "Charles Law" wrote:
>
>> > 1) Run the application in release mode. Applications with debug
>> > symbol
>> > baggage tend to run slower.
>>
>> It is currently running that way.
>>
>> > 2) Boost the priority of the thread.
>>
>> Currently set to AboveNormal.
>>
>> > 3) I'm not sure if this is redundant with #2 but you can try
>> > increasing
>> > the
>> > application's priority. Via Task Manager, select the process and
>> > select
>> > "Set
>> > Priority." I'm sure there's a way to do this via the framework or
>> > at least
>> > a
>> > Win32 API as well.
>>
>> Not tried, but I am inclined to agree with you assessment.
>>
>> > 4) Make sure the slowdown isn't caused by exceptions (even if
>> > handled in
>> > your worker thread). Exceptions will halt the thread as the
>> > framework
>> > processes it.
>>
>> Each task in the process is in a Try .. Catch block, and any
>> exception would
>> appear on screen. In this case I do not get any exception reported.
>>
>> > 5) Similarly to #3... be aware that some methods may throw and
>> > handle
>> > their
>> > own exceptions... all transparent to the caller. This will still
>> > slow
>> > everything down even though you never get the exception. You might
>> > be able
>> > to
>> > find the offending method by going to Debug|Exceptions and setting
>> > ALL
>> > exceptions to 'Break into Debugger' regardless if the exception is
>> > handled.
>>
>> The data in these tasks are pretty constant, so I would expect the
>> exceptions to be constant too, if there are any. The extra time does
>> not
>> always appear in the same place (or at all), but the data do not
>> change.
>>
>> >
>> > In the end, after all is said and done, it might be due to garbage
>> > collection. Garbage collection will pause your app momentarily.
>> > There are
>> > tricks to minimize this and effective object management and pooling
>> > helps
>> > (are you instantiating and releasing a lot of non-value type
>> > objects?).
>>
>> This is certainly one of my concerns, but I am unsure how I can
>> restrict
>> garbage collection to non-time sensitive areas of my code. And yes, I
>> am
>> creating a lot of non-value types; mostly associated with the raising
>> of
>> events.
>>
>> Charles
>>
>>
>> "CMM" <CM*@discussions.microsoft.com> wrote in message
>> news:F3**********************************@microsof t.com...
>> > 1) Run the application in release mode. Applications with debug
>> > symbol
>> > baggage tend to run slower.
>> > 2) Boost the priority of the thread.
>> > 3) I'm not sure if this is redundant with #2 but you can try
>> > increasing
>> > the
>> > application's priority. Via Task Manager, select the process and
>> > select
>> > "Set
>> > Priority." I'm sure there's a way to do this via the framework or
>> > at least
>> > a
>> > Win32 API as well.
>> > 4) Make sure the slowdown isn't caused by exceptions (even if
>> > handled in
>> > your worker thread). Exceptions will halt the thread as the
>> > framework
>> > processes it.
>> > 5) Similarly to #3... be aware that some methods may throw and
>> > handle
>> > their
>> > own exceptions... all transparent to the caller. This will still
>> > slow
>> > everything down even though you never get the exception. You might
>> > be able
>> > to
>> > find the offending method by going to Debug|Exceptions and setting
>> > ALL
>> > exceptions to 'Break into Debugger' regardless if the exception is
>> > handled.
>> >
>> > In the end, after all is said and done, it might be due to garbage
>> > collection. Garbage collection will pause your app momentarily.
>> > There are
>> > tricks to minimize this and effective object management and pooling
>> > helps
>> > (are you instantiating and releasing a lot of non-value type
>> > objects?).
>> >
>> >
>> > "Charles Law" wrote:
>> >
>> >> Hi guys
>> >>
>> >> I have a time critical process, running on a worker thread. By
>> >> "time
>> >> critical", I mean that certain parts of the process must be
>> >> completed in
>> >> a
>> >> specific time frame. The time when the process starts is not
>> >> especially
>> >> important, but it must be complete within a small number of
>> >> seconds.
>> >>
>> >> The operations I am performing do not take a long time (hundreds
>> >> of
>> >> milliseconds), but as each part of the process is complete, my
>> >> worker
>> >> thread
>> >> raises an event that is handled by the UI thread, to update a rich
>> >> text
>> >> control with details of the completed operation. I am using a rich
>> >> text
>> >> box
>> >> so that when a failure occurs I can colour the message red.
>> >>
>> >> The problem I have is that sometimes, for no apparent reason, a
>> >> step in
>> >> my
>> >> process takes an inordinate amount of time, e.g 2.5 seconds
>> >> instead of
>> >> perhaps 300 ms. When this happens, the complete process overruns
>> >> my time
>> >> frame, and it has to be repeated. When I repeat the process there
>> >> is
>> >> every
>> >> chance that it completes in a realistic time, and all is well. If
>> >> I stop
>> >> outputting to the screen, I do not get the problem.
>> >>
>> >> When updating the screen on the UI thread, I use BeginInvoke, to
>> >> marshal
>> >> the
>> >> operation to the correct thread, and so as not to hold up the
>> >> worker
>> >> thread,
>> >> but this does not seem to help.
>> >>
>> >> I realise that Windows (XP in this case) is not the ideal o/s for
>> >> this
>> >> type
>> >> of application, but does anyone have any ideas about how I could
>> >> make my
>> >> application more deterministic? I am not certain what is going on
>> >> in
>> >> these
>> >> 2.5 seconds, so it might be useful if I could find out, but I am
>> >> not sure
>> >> how I would do that.
>> >>
>> >> TIA
>> >>
>> >> Charles
>> >>
>> >>
>> >>
>>
>>
>>



Jul 21 '05 #48

P: n/a
CMM
> Think very carefully about it. If the purpose of Control.BeginInvoke is to
"execute on the thread that the control was created on", why would a third
thread from the thread pool be involved?
To return execution to the caller of as quickly as possible. If BeginInvoke
were truly asynchronous, why should the caller have to wait around for the
method to do whatever work it has to do like prepare and post a message via
the message pump (or whatever it does to queue the control call) and then
finally return execution to the caller. Although... perhaps it is more
expensive to pick up a new thread for this purpose. IMO, picking up threads
from the threadpool isn't as fast as it should be (sometimes taking a good
500ms or more). I'm not saying I'm correct about BeginInvoke... just thinking
out loud about the possibilities. :-)

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."

IMHO that sounds like a serious documentation error! I will check with MS to
make sure. I would expect the paragraph to read something like: "Note The
BeginInvoke method calls the specified delegate back on the control's UI
thread. You should not block the control's UI thread for any length of
time."

The first paragraph is the important one. "Executes the specified delegate
asynchronously on the thread that the control's underlying handle was
created on."

Think very carefully about it. If the purpose of Control.BeginInvoke is to
"execute on the thread that the control was created on", why would a third
thread from the thread pool be involved? Ergo the statement you quoted is
highly suspect and I will check with MS on it!
I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Sounds like you are double queuing the request, which IMHO is one queuing
too many. In other words it makes more sense when the worker thread calls
BeginInvoke, BeginInvoke simply queues the request for the main thread to
execute it. Rather then have the worker thread, queue a request for the
thread pool, then the thread pool simply queues the request for the UI
thread.

I don't have the Rotor source loaded, however using ILDASM & Rotor,
Control.BeginInvoke calls Control.MarshaledInvoke, which registers a private
windows message and calls the win32 GetWindowThreadProcessId & PostMessage
APIs. I don't see any reference to the Thread Pool in the implementation of
Control.BeginInvoke...

I will post something to MS about the documentation...

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C2**********************************@microsof t.com...
Control.BeginInvoke does not "spawn a thread", it sounds like you are
thinking Delegate.BeginInvoke which needs to "spawn a thread"!


From the MSDN documentation for *Control.BeginInvoke*
"Note The BeginInvoke method calls the specified delegate back on a
different thread pool thread. You should not block a thread pool thread
for
any length of time."

I suspect what happens (indeed it seems to me that it HAS to happen this
way) behind the scenes is that WorkerThread calls BeginInvoke, BeginInvoke
spawns thread to queue the delegate call, Execution returns to
WorkerThread,
The New thread "queues" the call that will eventually occur on the UI
thread.
Makes sense to me. ;-)

Having said that, I agree with your 80/20 characterization. It seems to me
that the chances of his bottleneck being the event model is low compared
to
other possibilities.

<<snip>>

Jul 21 '05 #49

P: n/a
CMM,
To return execution to the caller of as quickly as possible. Huh?
If BeginInvoke
were truly asynchronous, Control.BeginInvoke is truly asynchronous! As is Delegate.BeginInvoke. Its
simply that they are implemented is different.
why should the caller have to wait around for the
method to do whatever work it has to do like prepare Because the delegate & parameters that are needed needs to be "copied" from
the worker thread to the UI thread. I hope you agree that even
Delegate.BeginInvoke needs to "copy" the delegate & parameters from the
worker thread to the thread pool thread. This "copying" can be called
marshalling . In both cases the delegate & parameters need to be marshaled
from one thread to the other.

NOTE: Unless you are crossing an app domain, the marshalling here only needs
to save a reference to the delegate & parameters to be sent so the other
thread can use them. When you cross an app domain the objects may need to be
serialized & deserialized on the other side...
and post a message via
the message pump

The message pump itself runs on the UI thread, it is the Application.Run
call that is either directly or indirectly called when you start your
application. I would expect Thread Pool threads to have something very
similar to a message pump, however rather being based on Win32 message
queues (PostMessage, GetMessage apis) that is uses a System.Collection.Queue
object.

Hope this helps
Jay
"CMM" <CM*@discussions.microsoft.com> wrote in message
news:99**********************************@microsof t.com...
Think very carefully about it. If the purpose of Control.BeginInvoke is
to
"execute on the thread that the control was created on", why would a
third
thread from the thread pool be involved?


To return execution to the caller of as quickly as possible. If
BeginInvoke
were truly asynchronous, why should the caller have to wait around for the
method to do whatever work it has to do like prepare and post a message
via
the message pump (or whatever it does to queue the control call) and then
finally return execution to the caller. Although... perhaps it is more
expensive to pick up a new thread for this purpose. IMO, picking up
threads
from the threadpool isn't as fast as it should be (sometimes taking a good
500ms or more). I'm not saying I'm correct about BeginInvoke... just
thinking
out loud about the possibilities. :-)

"Jay B. Harlow [MVP - Outlook]" wrote:
CMM,
> From the MSDN documentation for *Control.BeginInvoke*
> "Note The BeginInvoke method calls the specified delegate back on a
> different thread pool thread. You should not block a thread pool thread
> for
> any length of time."

IMHO that sounds like a serious documentation error! I will check with MS
to
make sure. I would expect the paragraph to read something like: "Note
The
BeginInvoke method calls the specified delegate back on the control's UI
thread. You should not block the control's UI thread for any length of
time."

The first paragraph is the important one. "Executes the specified
delegate
asynchronously on the thread that the control's underlying handle was
created on."

Think very carefully about it. If the purpose of Control.BeginInvoke is
to
"execute on the thread that the control was created on", why would a
third
thread from the thread pool be involved? Ergo the statement you quoted is
highly suspect and I will check with MS on it!
> I suspect what happens (indeed it seems to me that it HAS to happen
> this
> way) behind the scenes is that WorkerThread calls BeginInvoke,
> BeginInvoke
> spawns thread to queue the delegate call, Execution returns to
> WorkerThread,
> The New thread "queues" the call that will eventually occur on the UI
> thread.
> Makes sense to me. ;-)

Sounds like you are double queuing the request, which IMHO is one queuing
too many. In other words it makes more sense when the worker thread calls
BeginInvoke, BeginInvoke simply queues the request for the main thread to
execute it. Rather then have the worker thread, queue a request for the
thread pool, then the thread pool simply queues the request for the UI
thread.

I don't have the Rotor source loaded, however using ILDASM & Rotor,
Control.BeginInvoke calls Control.MarshaledInvoke, which registers a
private
windows message and calls the win32 GetWindowThreadProcessId &
PostMessage
APIs. I don't see any reference to the Thread Pool in the implementation
of
Control.BeginInvoke...

I will post something to MS about the documentation...

Hope this helps
Jay

"CMM" <CM*@discussions.microsoft.com> wrote in message
news:C2**********************************@microsof t.com...
>> Control.BeginInvoke does not "spawn a thread", it sounds like you are
>> thinking Delegate.BeginInvoke which needs to "spawn a thread"!
>
> From the MSDN documentation for *Control.BeginInvoke*
> "Note The BeginInvoke method calls the specified delegate back on a
> different thread pool thread. You should not block a thread pool thread
> for
> any length of time."
>
> I suspect what happens (indeed it seems to me that it HAS to happen
> this
> way) behind the scenes is that WorkerThread calls BeginInvoke,
> BeginInvoke
> spawns thread to queue the delegate call, Execution returns to
> WorkerThread,
> The New thread "queues" the call that will eventually occur on the UI
> thread.
> Makes sense to me. ;-)
>
> Having said that, I agree with your 80/20 characterization. It seems to
> me
> that the chances of his bottleneck being the event model is low
> compared
> to
> other possibilities.
>

<<snip>>

Jul 21 '05 #50

77 Replies

This discussion thread is closed

Replies have been disabled for this discussion.