PC Review


Reply
Thread Tools Rate Thread

2 different threads checking on same variable scenario

 
 
David
Guest
Posts: n/a
 
      9th May 2007
I am trying to get this straight in my head so I can implement.

I wrote a small utility some time ago in c# that utilized a handful of
threads. That scenario was one main thread manually spawning a handfull of
worker threads, then waiting for all of them to complete before moving on. I
believe I used array of ManualResetEvents and the WaitAll() method to do
this. All the worker threads used a shared object (a common place to
collect and output data). I recall having to use 'lock' (essentially the
monitor class) to synchronize access to this object. All works great. That
was a while ago and now I have a new scenario (much simpler, I think) but I
can't get a solution straight in my head. I'm using this past example
because it is my only point of reference for mutlithreaded scenarios.

now, I'm writting a small utility (console app) that is using the asynch
programming pattern. I simply want the main thread to show some kind of
progress indicator (writing dots to screen, whatever) after calling an
asynch method and then move on after asnych operation completes. So
currently the code is structured so that the asynch operation is started and
the main thread just waits using WaitOne() until the asynch operation
signals the manualResentEvent. Now I want to implement the progress
indicator but I'm not sure how. I'm assuming I need to get rid of the
manualResetEvent and waitOne() setup and move to checking some variable that
both threads have access to?

while (sharedVar) {do progress indicator thing}

Based on what I learned from the older project I described, I immediately
thought to just use lock. But then I thought that the lock would never be
released from the progress indicator loop in order for the other thread to
gain the lock and modify the sharedVar so the loop could end?

any input on how I should be handling this scenario would be greatly
appreciated.


 
Reply With Quote
 
 
 
 
Alberto Poblacion
Guest
Posts: n/a
 
      9th May 2007
"David" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
> while (sharedVar) {do progress indicator thing}


If the sharedVar is a boolean, you don't need any kind of lock. Assigning
a value to a bolean variable and testing the value of a boolean variable are
thread-safe operations.

 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      9th May 2007
On May 9, 3:31 pm, "Alberto Poblacion" <earthling-
quitaestoparacontes...@poblacion.org> wrote:
> > while (sharedVar) {do progress indicator thing}

>
> If the sharedVar is a boolean, you don't need any kind of lock. Assigning
> a value to a bolean variable and testing the value of a boolean variable are
> thread-safe operations.


Not true, unless sharedVar is declared to be volatile. If it's not
volatile, there's nothing to stop the reading thread from caching the
value and never rereading it from main memory.

I'd either make it volatile, or make it a property which took out a
lock for reading and writing.

Jon

 
Reply With Quote
 
David
Guest
Posts: n/a
 
      9th May 2007
thanks Alberto,
thats reminds me of some of the info I got during the last project... is
this because reading/writing boolean value is an 'atomic' operation?
Wondering if I'm remembering correctly. I think the same place that I
learned of atomic operations also talked about using 'volatile' keyword when
declaring the variables to be used like this? Do I need to declare my bool
shardVar in any special way?

Thanks again, I appreciate it. I looked into this stuff some time ago but
havn't used it since... I'm just putting together a really small utility
that I need to do fast so I was really hoping to not have to go through all
the research I did last time. You are saving me a lot of time. Thank you.

"Alberto Poblacion" <earthling-(E-Mail Removed)> wrote
in message news:(E-Mail Removed)...
> "David" <(E-Mail Removed)> wrote in message
> news:%(E-Mail Removed)...
>> while (sharedVar) {do progress indicator thing}

>
> If the sharedVar is a boolean, you don't need any kind of lock.
> Assigning a value to a bolean variable and testing the value of a boolean
> variable are thread-safe operations.
>



 
Reply With Quote
 
David
Guest
Posts: n/a
 
      9th May 2007
whoa, quick responses on this thread. Thanks!
I replied before seeing Jon's reply. Jon answered my question about
declaring it 'specially'. Use volatile.

thanks Jon.

"Jon Skeet [C# MVP]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On May 9, 3:31 pm, "Alberto Poblacion" <earthling-
> quitaestoparacontes...@poblacion.org> wrote:
>> > while (sharedVar) {do progress indicator thing}

>>
>> If the sharedVar is a boolean, you don't need any kind of lock.
>> Assigning
>> a value to a bolean variable and testing the value of a boolean variable
>> are
>> thread-safe operations.

>
> Not true, unless sharedVar is declared to be volatile. If it's not
> volatile, there's nothing to stop the reading thread from caching the
> value and never rereading it from main memory.
>
> I'd either make it volatile, or make it a property which took out a
> lock for reading and writing.
>
> Jon
>



 
Reply With Quote
 
Jon Skeet [C# MVP]
Guest
Posts: n/a
 
      9th May 2007
On May 9, 3:48 pm, "David" <nos...@nospam.com> wrote:
> thats reminds me of some of the info I got during the last project... is
> this because reading/writing boolean value is an 'atomic' operation?


Yes, it's atomic, but it's not volatile unless you declare it to be.

> Wondering if I'm remembering correctly. I think the same place that I
> learned of atomic operations also talked about using 'volatile' keyword when
> declaring the variables to be used like this? Do I need to declare my bool
> shardVar in any special way?


See http://pobox.com/~skeet/csharp/threads/volatility.shtml

Jon

 
Reply With Quote
 
David
Guest
Posts: n/a
 
      9th May 2007
thanks Jon. I remember now, I have your page on my browser favorites... it
helped me before. I'll revew it again.

"Jon Skeet [C# MVP]" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> On May 9, 3:48 pm, "David" <nos...@nospam.com> wrote:
>> thats reminds me of some of the info I got during the last project... is
>> this because reading/writing boolean value is an 'atomic' operation?

>
> Yes, it's atomic, but it's not volatile unless you declare it to be.
>
>> Wondering if I'm remembering correctly. I think the same place that I
>> learned of atomic operations also talked about using 'volatile' keyword
>> when
>> declaring the variables to be used like this? Do I need to declare my
>> bool
>> shardVar in any special way?

>
> See http://pobox.com/~skeet/csharp/threads/volatility.shtml
>
> Jon
>



 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      9th May 2007
"David" <(E-Mail Removed)> wrote in message
news:%(E-Mail Removed)...
>I am trying to get this straight in my head so I can implement.
>
> I wrote a small utility some time ago in c# that utilized a handful of
> threads. That scenario was one main thread manually spawning a handfull of
> worker threads, then waiting for all of them to complete before moving on.
> I believe I used array of ManualResetEvents and the WaitAll() method to do
> this. All the worker threads used a shared object (a common place to
> collect and output data). I recall having to use 'lock' (essentially the
> monitor class) to synchronize access to this object. All works great. That
> was a while ago and now I have a new scenario (much simpler, I think) but
> I can't get a solution straight in my head. I'm using this past example
> because it is my only point of reference for mutlithreaded scenarios.
>
> now, I'm writting a small utility (console app) that is using the asynch
> programming pattern. I simply want the main thread to show some kind of
> progress indicator (writing dots to screen, whatever) after calling an
> asynch method and then move on after asnych operation completes. So
> currently the code is structured so that the asynch operation is started
> and the main thread just waits using WaitOne() until the asynch operation
> signals the manualResentEvent. Now I want to implement the progress
> indicator but I'm not sure how. I'm assuming I need to get rid of the
> manualResetEvent and waitOne() setup and move to checking some variable
> that both threads have access to?
>
> while (sharedVar) {do progress indicator thing}
>
> Based on what I learned from the older project I described, I immediately
> thought to just use lock. But then I thought that the lock would never be
> released from the progress indicator loop in order for the other thread to
> gain the lock and modify the sharedVar so the loop could end?
>
> any input on how I should be handling this scenario would be greatly
> appreciated.
>



No need for a shared variable, just keep synchronizing both threads as you
did, but use the WaitOne overhead that takes a TimeSpan. Set the Timespan to
a reasonable value depending on the duration of the other threads task,
update the user interface (the progress indicator) each time WaitOne
times-out.

Willy.


 
Reply With Quote
 
David
Guest
Posts: n/a
 
      9th May 2007
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 (shared var vs waitOne overload with
timespan)? Without looking yet the waitOne with timespan overload sounds
like it may be more fitting for my particular need (progress indicator)... I
was probably going to just use the shared var to control the loop and use
console.writeline()'s and short thread.sleep()'s within the loop.

"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
news:AEC47416-1022-4D59-A9CA-(E-Mail Removed)...
> "David" <(E-Mail Removed)> wrote in message
> news:%(E-Mail Removed)...
>>I am trying to get this straight in my head so I can implement.
>>
>> I wrote a small utility some time ago in c# that utilized a handful of
>> threads. That scenario was one main thread manually spawning a handfull
>> of worker threads, then waiting for all of them to complete before moving
>> on. I believe I used array of ManualResetEvents and the WaitAll() method
>> to do this. All the worker threads used a shared object (a common place
>> to collect and output data). I recall having to use 'lock' (essentially
>> the monitor class) to synchronize access to this object. All works great.
>> That was a while ago and now I have a new scenario (much simpler, I
>> think) but I can't get a solution straight in my head. I'm using this
>> past example because it is my only point of reference for mutlithreaded
>> scenarios.
>>
>> now, I'm writting a small utility (console app) that is using the asynch
>> programming pattern. I simply want the main thread to show some kind of
>> progress indicator (writing dots to screen, whatever) after calling an
>> asynch method and then move on after asnych operation completes. So
>> currently the code is structured so that the asynch operation is started
>> and the main thread just waits using WaitOne() until the asynch operation
>> signals the manualResentEvent. Now I want to implement the progress
>> indicator but I'm not sure how. I'm assuming I need to get rid of the
>> manualResetEvent and waitOne() setup and move to checking some variable
>> that both threads have access to?
>>
>> while (sharedVar) {do progress indicator thing}
>>
>> Based on what I learned from the older project I described, I immediately
>> thought to just use lock. But then I thought that the lock would never be
>> released from the progress indicator loop in order for the other thread
>> to gain the lock and modify the sharedVar so the loop could end?
>>
>> any input on how I should be handling this scenario would be greatly
>> appreciated.
>>

>
>
> No need for a shared variable, just keep synchronizing both threads as you
> did, but use the WaitOne overhead that takes a TimeSpan. Set the Timespan
> to a reasonable value depending on the duration of the other threads task,
> update the user interface (the progress indicator) each time WaitOne
> times-out.
>
> Willy.
>
>



 
Reply With Quote
 
Peter Duniho
Guest
Posts: n/a
 
      9th May 2007
On Wed, 09 May 2007 08:58:29 -0700, David <(E-Mail Removed)> wrote:

> 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 "checkpoints" 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
 
Reply With Quote
 
 
 
Reply

Thread Tools
Rate This Thread
Rate This Thread:

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Fastest way to update an integer variable across threads =?Utf-8?B?QnVkZHlXb3Jr?= Microsoft C# .NET 3 5th Oct 2006 04:03 PM
checking hte existence of an environment variable Kok Yong Lee Microsoft Windows 2000 CMD Promt 5 12th May 2006 04:57 AM
Monitoring threads and accessing a shared variable Jon C Microsoft VB .NET 2 15th Nov 2005 12:52 PM
Checking for variable type Pavils Jurjans Microsoft C# .NET 4 26th May 2004 06:34 PM
checking for variable =?Utf-8?B?bHdn?= Microsoft Windows 2000 CMD Promt 8 8th Jan 2004 01:18 AM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 12:32 PM.