On Wed, 09 May 2007 08:58:29 -0700, David <no****@nospam. comwrote:
interesting... I'll check out that overload. Do you see this as just
'another' way to accomplish this or are there certain pros/cons that may
make one a better choice than the other
To me, it depends on what you intend to do in your main thread's loop.
Because you are implementing a console application here, it seems to me
that a third way to implement this would be to simply have the main thread
call some "do work" function repeatedly. That function would make as much
progress toward the goal as you want for each "update" (where an "update"
may just be writing a new "." to the console output), would return to the
caller so it can handle the "update" and when called again would resume
where it left off.
This would be especially appropriate if the work you need to do is already
conveniently broken into multiple chunks (for example, it involves a loop
that processes a list of files), where the the top-level loop in your main
thread can handle managing the list of chunks to process (that way the "do
work" function doesn't even need to maintain any state between calls...the
caller is handling that for it).
Depending on just what you intended to do in your "do progress indicator
thing" loop, there may be a fourth option. That is, use an auto-reset
wait event to block the main thread between progress updates, a flag to
indicate when the work has been done, and then have the worker thread set
the flag when it's done, and intermittently set the wait event to indicate
to the main thread to update the progress.
To summarize, here's four different ways I see as having been mentioned in
this thread:
#1:
volatile bool fDone = false;
// start worker thread
while (!fDone)
{
Sleep(...);
// update progress
}
In the worker thread, fDone is set when the work has been completed.
#2:
AutoResetEvent event = new AutoResetEvent( false);
// start worker thread
while (!event.WaitOne (new TimeSpan(0, 0, 1), false))
{
// update progress
}
In the worker thread, the event is set when the work has been completed.
#3:
AutoResetEvent event = new AutoResetEvent( false);
volatile bool fDone = false;
// start worker thread
while (!fDone)
{
event.WaitOne() ;
// update progress
}
In the worker thread, the event is set when the main thread should update
the progress indication, and the fDone flag is set when the work is done..
#4:
foreach (WorkItem item in WorkCollection)
{
item.DoWork();
// update progress
}
There's no worker thread. The main thread just iteratively performs work,
updating progress between calls to the method that does work. You may or
may not have exactly the above data structure design. For example,
instead of having a class that encapsulates the work items, you might just
have some list of objects (strings containing filenames, for example), and
a method in some other class (your main Program class, for example) that
does some work on a single object (takes a filename and does some
processing on that file, for example).
To compare and contrast the various methods:
The first two provide progress updates on a strictly time-based
interval. The upside is that you always have some feedback to the user.
The downside is that feedback doesn't really indicate what progress has
been made; in fact, the worker thread could completely lock up and you'd
still show progress as being made.
Between the first two, I don't see too much difference. They both use
slightly different mechanisms to accomplish very much the same thing.
The second two provide progress updates that are tied to the actual
work being done. The upside is that you have direct indication of the
progress being made. The downside is that the feedback may or may not be
provided in a timely manner. Both of the second pair do rely on the work
being done having regular "checkpoint s" at which it makes sense to update
the progress.
Between the second pair, probably the biggest difference is that with
option #4, you don't even have to make a new thread. It does rely on the
main thread having more involvement with the work being done, however. If
you want greater encapsulation, option #3 is probably more desirable.
This is not even a complete analysis. As you can see, there's a wide
variety of approaches to doing what you want. They are roughly equivalent
in that they all get the job done, but they all have different specific
behaviors, and different demands on the architecture of the part of your
code that actually does work.
I hope I have helped, rather than further confusing the issue. I realize
sometimes all someone wants is to be told "do it this way"...I even find
myself in that position sometimes. :)
Pete