Threads - WaitForMultiObjects equivalent in C#

For the longest, for my non-I/O based thread work, I used 
WaitForMultiObjects (WFMO) as a way to wait for a set of worker 
threads to complete, simpling by putting the thread handles in an 
array and passing it to WFMO, for example:

//  Wait (infinitely) for 10 threads to ALL complete.

      HANDLE hThreads[10] = {0};

      for(int i=0; i<10; i++) {
           hThreads[i] = CreateThread(.......);
      }

      WFMO(hThreads,10,TRUE,INFINITE);

I wish to do the same in C#, I can start the threads, but I don't see 
a simple WFMO() idea.

Ideally, I wish to have a callback version of WFMO() so that an event 
is called (i.e. a OnThreadsFinish() event) signally when all threads 
are finished.

Note: I was able to come up with a method, but it seems there is a 
more natural way in .NET.  What I do is:

   1) Create X BackgroundWorkers and put it into an array Workers[]

   2) Then have a DoEvents loop:

     int done = 0;
     while (done < X)
     {
         done = 0;
         for (int i=0; i < X; i++) {
             if (!Workers[i].IsBusy) done++;
         }
         Application.DoEvents();
     }

     // THREADS WE DONE - do whatever

I only used a Thread Pool.  But I don't see a function there to 
determine when all the queued threads are complete.

Thanks

-- 
HLS
0
Hector
6/1/2010 7:55:19 PM
dotnet.languages.csharp 1931 articles. 0 followers. Follow

22 Replies
1195 Views

Similar Articles

[PageSpeed] 32

Hector Santos wrote :
> For the longest, for my non-I/O based thread work, I used WaitForMultiObjects 
> (WFMO) as a way to wait for a set of worker threads to complete, simpling by 
> putting the thread handles in an array and passing it to WFMO, for example:
>
> //  Wait (infinitely) for 10 threads to ALL complete.
>
>       HANDLE hThreads[10] = {0};
>
>       for(int i=0; i<10; i++) {
>            hThreads[i] = CreateThread(.......);
>       }
>
>       WFMO(hThreads,10,TRUE,INFINITE);
>
> I wish to do the same in C#, I can start the threads, but I don't see a 
> simple WFMO() idea.
>
> Ideally, I wish to have a callback version of WFMO() so that an event is 
> called (i.e. a OnThreadsFinish() event) signally when all threads are 
> finished.
>
> Note: I was able to come up with a method, but it seems there is a more 
> natural way in .NET.  What I do is:
>
>    1) Create X BackgroundWorkers and put it into an array Workers[]
>
>    2) Then have a DoEvents loop:
>
>      int done = 0;
>      while (done < X)
>      {
>          done = 0;
>          for (int i=0; i < X; i++) {
>              if (!Workers[i].IsBusy) done++;
>          }
>          Application.DoEvents();
>      }
>
>      // THREADS WE DONE - do whatever
>
> I only used a Thread Pool.  But I don't see a function there to determine 
> when all the queued threads are complete.
>
> Thanks

I think you might be lookign for hte WaitHandle.WaitAll method?

-- 
Tom Shelton


0
Tom
6/1/2010 8:07:19 PM
Tom Shelton wrote:

>> I only used a Thread Pool.  But I don't see a function there to 
>> determine when all the queued threads are complete.
>>
>> Thanks
> 
> I think you might be lookign for hte WaitHandle.WaitAll method?


Yes, thanks tom. I had missed it somehow in MSDN jumping all over the 
place and got side tracked with MSDN examples with a MSDN comment 
regarding "multi-tasking" behavior on single vs multi-processor/core 
machines. I have to pencil that and go over that before I complete my 
work.

But I had finally found it at this "Threading in C#" web site with 
excellent summary background information for people like me. All 
concepts consolidated right at the top! BOOK MARK IT! :)

       http://www.albahari.com/threading/part3.aspx

MSDN threading pages also has some needed background information 
regarding performance.

What I ended up doing is writing a class that spawns the dynamically 
allocated workers with an additional optional thread to monitor the 
completion and fire an OnMultiThreadComplete event. The default is to 
just wait in the calling thread with a function that does the loop I 
showed in my last post. That works nicely as well.

BTW, I found the ultimate MSDN Online Help GUI - CHROME!!! IE is just 
too slow and it is superior with the "smart auto search" as you type. 
Seems like GOOGLE indexed the entire MSDN content!  Check it out! 
Honestly, it isn't so bad now. THe IDE help simply sucks. But with 
CHROME it is so fast that its like the old VC6 MSDN but better because 
the #1 problem there was not being able to open many help page 
instances.  Any way, thats a different topic. :)


-- Coming soon, WCLEX - Wildcat! Live Exchange!
HLS
0
Hector
6/1/2010 9:15:03 PM
Hector Santos wrote on 6/1/2010 :
> Tom Shelton wrote:
>
>>> I only used a Thread Pool.  But I don't see a function there to determine 
>>> when all the queued threads are complete.
>>>
>>> Thanks
>> 
>> I think you might be lookign for hte WaitHandle.WaitAll method?
>
>
> Yes, thanks tom. I had missed it somehow in MSDN jumping all over the place 
> and got side tracked with MSDN examples with a MSDN comment regarding 
> "multi-tasking" behavior on single vs multi-processor/core machines. I have 
> to pencil that and go over that before I complete my work.
>
> But I had finally found it at this "Threading in C#" web site with excellent 
> summary background information for people like me. All concepts consolidated 
> right at the top! BOOK MARK IT! :)
>
>        http://www.albahari.com/threading/part3.aspx
>
> MSDN threading pages also has some needed background information regarding 
> performance.
>
> What I ended up doing is writing a class that spawns the dynamically 
> allocated workers with an additional optional thread to monitor the 
> completion and fire an OnMultiThreadComplete event. The default is to just 
> wait in the calling thread with a function that does the loop I showed in my 
> last post. That works nicely as well.
>
> BTW, I found the ultimate MSDN Online Help GUI - CHROME!!! IE is just too 
> slow and it is superior with the "smart auto search" as you type. Seems like 
> GOOGLE indexed the entire MSDN content!  Check it out! Honestly, it isn't so 
> bad now. THe IDE help simply sucks. But with CHROME it is so fast that its 
> like the old VC6 MSDN but better because the #1 problem there was not being 
> able to open many help page instances.  Any way, thats a different topic. :)
>
>
> -- Coming soon, WCLEX - Wildcat! Live Exchange!
> HLS

I'm glad you got it worked out.  As for using Chrome - no thanks.  I'll 
stick to firefox.  May not be as fast, but IMHO, Google is the current 
evil empire :)

-- 
Tom Shelton


0
Tom
6/1/2010 10:27:29 PM
Tom Shelton wrote:
> Hector Santos wrote :
>> For the longest, for my non-I/O based thread work, I used 
>> WaitForMultiObjects (WFMO) as a way to wait for a set of worker 
>> threads to complete, simpling by putting the thread handles in an 
>> array and passing it to WFMO, for example:
>>
>> //  Wait (infinitely) for 10 threads to ALL complete.
>>
>>       HANDLE hThreads[10] = {0};
>>
>>       for(int i=0; i<10; i++) {
>>            hThreads[i] = CreateThread(.......);
>>       }
>>
>>       WFMO(hThreads,10,TRUE,INFINITE);
>>
>> I wish to do the same in C#, I can start the threads, but I don't see 
>> a simple WFMO() idea.
>>
>> [...]
> 
> I think you might be lookign for hte WaitHandle.WaitAll method?

Hector probably would think that's the right equivalent to what he's 
used to.

However, IMHO it is a good idea to get used to using the .NET-native 
threading and synchronization techniques where applicable.

In this particular example, this means a few things:

   • Don't block the GUI thread.  In other words, the very design idea 
of waiting on all the worker threads is fundamentally flawed.

   • Use the features built into BackgroundWorker to track and respond 
to  changes in the active thread count.

   • In other cases, use the Monitor class for cross-thread signaling.

The first two points go together, in that using the BackgroundWorker 
correctly means that the GUI thread does not wind up blocked.  Here's an 
example:

   void RunWorkers(int count)
   {
     for (int i = 0; i < count; i++)
     {
       BackgroundWorker worker = new BackgroundWorker();
       int delay = i * 500;

       worker.DoWork += (sender, e) =>
       {
         // dummy work
         Thread.Sleep(delay);
       };

       worker.RunWorkerCompleted += (sender, e) =>
       {
         // Signal completion
         if (--count == 0)
         {
           AllWorkersDone();
         }
       };

       worker.RunWorkerAsync();
     }
   }

   void AllWorkersDone()
   {
     // do whatever here
   }

Note that the above assumes RunWorkers() is being called on the main GUI 
thread.  Which means that each RunWorkerCompleted event handler is also 
executed on the main GUI thread.  This has a couple of useful effects:

   • The "count" variable, used directly in RunWorkers() and as a 
captured variable in the RunWorkerCompleted event handlers, is only ever 
used in a single thread, ensuring synchronization.

   • The AllWorkersDone() method itself will be executed on the main GUI 
thread, just as if the original method had gotten stuck in a loop 
waiting for the threads to complete.

Of course, the big difference being that the main GUI thread doesn't 
wind up blocked as in the original implementation.

Pete
0
Peter
6/2/2010 5:28:29 AM
Peter Duniho wrote:

>   void RunWorkers(int count)
>   {
>     for (int i = 0; i < count; i++)
>     {
>       BackgroundWorker worker = new BackgroundWorker();
>       int delay = i * 500;
> 
>       worker.DoWork += (sender, e) =>
>       {
>         // dummy work
>         Thread.Sleep(delay);
>       };
> 
>       worker.RunWorkerCompleted += (sender, e) =>
>       {
>         // Signal completion
>         if (--count == 0)
>         {
>           AllWorkersDone();
>         }
>       };
> 
>       worker.RunWorkerAsync();
>     }
>   }
> 
>   void AllWorkersDone()
>   {
>     // do whatever here
>   }
> 
>   • The "count" variable, used directly in RunWorkers() and as a 
> captured variable in the RunWorkerCompleted event handlers, is only ever 
> used in a single thread, ensuring synchronization.


Hi Pete,

I appreciate the example in using the anonymous functions!  Something 
I intend to master in C# :)

Just a few small notes:

1) As a principle, using time for synchronization is a engineering 
taboo in thread designs.  A Sleep() is not simulating work because 
there is no work being done and hence no other promotions of system 
overhead context switching and/or interrupts. Even then, inevitably, 
it will provide unexpected behavior when using a "random" or unknown 
thread residence time.

2) Using the loop limit in this example as a thread count "signal" is 
not good here. Any delay within the loop that is longer than any 
thread residency time will alter the captured count variable.

To illustrate, change the code to add a delay between thread startup 
to see what I mean:

        int delay = i*500;
        if (i == 1) {
            // i.e, Simulate Preparation work
            Thread.Sleep(100);
        }

Overall, from a software engineering standpoint, avoid thread designs 
based on time syncing and avoid using the common resource such as loop 
limit as the watch variable here.

Two simple solutions - set the thread count outside the loop, or first 
prepare the threads, much like a "Suspended" concept and then start it 
after the preparation.

   void RunWorkers(int count)
   {
     int threadCount = count;
     for (int i = 0; i < count; i++)
     {
       BackgroundWorker worker = new BackgroundWorker();
       int delay = i * 500;
       if (i == 1) {
          // i.e, Simulate Preparation work
          Thread.Sleep(100);
       }

       worker.DoWork += (sender, e) =>
       {
         // dummy work
         Thread.Sleep(delay);
       };

       worker.RunWorkerCompleted += (sender, e) =>
       {
         // Signal completion
         if (--threadCount == 0)
         {
           AllWorkersDone();
         }
       };

       worker.RunWorkerAsync();
     }
   }

or

   void RunWorkers(int count)
   {
     // prepare threads

     BackgroundWorker[] workers = new BackgroundWorker[count];
     for (int i = 0; i < count; i++)
     {
       worker[i] = new BackgroundWorker();
       int delay = i * 500;
       if (i == 1) {
          // i.e, Simulate Preparation work
          Thread.Sleep(100);
       }

       worker[i]DoWork += (sender, e) =>
       {
         // dummy work
         Thread.Sleep(delay);
       };

       worker[i].RunWorkerCompleted += (sender, e) =>
       {
         // Signal completion
         if (--Count == 0)
         {
           AllWorkersDone();
         }
       };
     }

     // start threads
     foreach (var w in workers) w.RunWorkerAsync();
   }


Anyway, I see your main layout method and it was very good to 
illustrate this using anonymous functions - learned a lot. Thanks.


-- 
HLS
0
Hector
6/2/2010 2:23:39 PM
Hector Santos wrote:
> [...]
> Just a few small notes:

Hector, you have completely missed the point of the code example, both 
in terms of what things in the code example are important, and in 
comprehending how the example actually works.

> 1) As a principle, using time for synchronization is a engineering taboo 
> in thread designs.  A Sleep() is not simulating work because there is no 
> work being done and hence no other promotions of system overhead context 
> switching and/or interrupts. Even then, inevitably, it will provide 
> unexpected behavior when using a "random" or unknown thread residence time.

As my comment that reads "dummy work" explains, the call to 
Thread.Sleep() has nothing to do with the code example.  It's there 
simply to simulate the worker thread taking some time to do work.  In a 
real implementation, the call to Thread.Sleep() would not be present, 
and its presence or lack of presence has no effect on whether the 
technique I've illustrated works or not.

If you feel more comfortable replacing the call to Thread.Sleep() with a 
busy loop, go right ahead.  It doesn't change the validity of the code 
example one bit, because the call to Thread.Sleep() has nothing to do 
with what's being illustrated.

> 2) Using the loop limit in this example as a thread count "signal" is 
> not good here. Any delay within the loop that is longer than any thread 
> residency time will alter the captured count variable.

You are also mistaken on your second point.  As I already pointed out, 
the thread-count variable is only ever used in a single thread: the main 
GUI thread.  The RunWorkerCompleted event handlers cannot execute until 
the method that is initializing the threads has returned, and only one 
event handler at a time can execute, because they all execute on the 
same thread.

> To illustrate, change the code to add a delay between thread startup to 
> see what I mean:
> 
>        int delay = i*500;
>        if (i == 1) {
>            // i.e, Simulate Preparation work
>            Thread.Sleep(100);
>        }

It would have been nice if you'd actually tried adding that code 
yourself.  Had you done so, you would have seen that it has no effect on 
the outcome of the code, other than to delay it of course.

> Overall, from a software engineering standpoint, avoid thread designs 
> based on time syncing and avoid using the common resource such as loop 
> limit as the watch variable here.

Again, there is nothing in my code that relies on "time synching".  The 
call to Thread.Sleep() is simply to simulate the worker thread doing 
something.  The code will work regardless of the time each worker thread 
spends doing work.

> Two simple solutions - set the thread count outside the loop, or first 
> prepare the threads, much like a "Suspended" concept and then start it 
> after the preparation.

Neither of those are required.  They only add complexity, for no benefit.

> [...]
> Anyway, I see your main layout method and it was very good to illustrate 
> this using anonymous functions - learned a lot. Thanks.

I hope that you will go back and review the code example more carefully. 
  As I said at the outset, it is a good idea to become familiar with the 
..NET-native techniques, and in this case that includes understanding 
what BackgroundWorker actually does and how it works.

In particular, knowing that the BackgroundWorker events, except for 
DoWork, always get raised on the same thread that created the 
BackgroundWorker instance (assuming that thread is one with a 
SynchronizationContext, such as a normal, Forms GUI thread) is critical 
in understanding why the code example I posted is correct.

Without that understanding, one might get distracted nit-picking aspects 
of the code that don't have anything to do with the actual example, and 
making incorrect statements about why one believes the code doesn't work 
as posted.

Pete
0
Peter
6/2/2010 3:25:57 PM
Hector Santos wrote:
> For the longest, for my non-I/O based thread work, I used
> WaitForMultiObjects (WFMO) as a way to wait for a set of worker threads
> to complete, simpling by putting the thread handles in an array and
> passing it to WFMO, for example:
>
> // Wait (infinitely) for 10 threads to ALL complete.
>
> HANDLE hThreads[10] = {0};
>
> for(int i=0; i<10; i++) {
> hThreads[i] = CreateThread(.......);
> }
>
> WFMO(hThreads,10,TRUE,INFINITE);
>
> I wish to do the same in C#, I can start the threads, but I don't see a
> simple WFMO() idea.
>
> Ideally, I wish to have a callback version of WFMO() so that an event is
> called (i.e. a OnThreadsFinish() event) signally when all threads are
> finished.
>
> Note: I was able to come up with a method, but it seems there is a more
> natural way in .NET. What I do is:
>
> 1) Create X BackgroundWorkers and put it into an array Workers[]
>
> 2) Then have a DoEvents loop:
>
> int done = 0;
> while (done < X)
> {
> done = 0;
> for (int i=0; i < X; i++) {
> if (!Workers[i].IsBusy) done++;
> }
> Application.DoEvents();
> }
>
> // THREADS WE DONE - do whatever
>
> I only used a Thread Pool. But I don't see a function there to determine
> when all the queued threads are complete.
>
> Thanks
>

A completely different approach would be to use Retlang.

The following illustrates what you're after:
http://code.google.com/p/retlang/wiki/SummationExample

HTH
0
Jason
6/2/2010 3:49:05 PM
Peter Duniho wrote:

> Hector Santos wrote:
>> [...]
>> Just a few small notes:
> 
> Hector, you have completely missed the point of the code example, both 
> in terms of what things in the code example are important, and in 
> comprehending how the example actually works.


Really?  I think you are assuming too to be saying that.

> As my comment that reads "dummy work" explains, the call to 
> Thread.Sleep() has nothing to do with the code example.  It's there 
> simply to simulate the worker thread taking some time to do work.  In a 
> real implementation, the call to Thread.Sleep() would not be present, 
> and its presence or lack of presence has no effect on whether the 
> technique I've illustrated works or not.


Its an important concept to not mix up SLEEP with ACTUAL THREAD WORK 
when it come to system stabilization.

>> 2) Using the loop limit in this example as a thread count "signal" is 
>> not good here. Any delay within the loop that is longer than any 
>> thread residency time will alter the captured count variable.
> 
> You are also mistaken on your second point.  As I already pointed out, 
> the thread-count variable is only ever used in a single thread: the main 
> GUI thread.  The RunWorkerCompleted event handlers cannot execute until 
> the method that is initializing the threads has returned, and only one 
> event handler at a time can execute, because they all execute on the 
> same thread.
> 
>> To illustrate, change the code to add a delay between thread startup 
>> to see what I mean:
>>
>>        int delay = i*500;
>>        if (i == 1) {
>>            // i.e, Simulate Preparation work
>>            Thread.Sleep(100);
>>        }
> 
> It would have been nice if you'd actually tried adding that code 
> yourself.  Had you done so, you would have seen that it has no effect on 
> the outcome of the code, other than to delay it of course.


I did.  This following illustrates the contention issue with count as 
I described.

using System;
using System.Text;
using System.ComponentModel;
using System.Threading;

namespace ConsoleApplet {

     class CoBackgroundWorker : BackgroundWorker
     {
         public int tid   = 0;
     }
     class WorkerJobs
     {
        void BeepDone()
        {
           Console.Beep(2000, 200);
           Console.Beep(1000, 50);
        }

        public void RunWorkers(int count)
        {
          Console.WriteLine("* Starting {0} Threads",count);
          for (int i = 0; i < count; i++)
          {
            CoBackgroundWorker worker = new CoBackgroundWorker();
            worker.tid = i;

            int delay = i*500;
            if (i == 1) Thread.Sleep(100);

            worker.DoWork += (sender, e) =>
            {
                // dummy work
                CoBackgroundWorker w = sender as CoBackgroundWorker;
                Console.WriteLine("- tid: {0} delay={2} count={3}",
                          w.tid, delay ,count);
                Thread.Sleep(delay);
            };

            worker.RunWorkerCompleted += (sender, e) =>
            {
              CoBackgroundWorker w = sender as CoBackgroundWorker;
              WorkerDone(w.tid, count);
              if (--count == 0)
              {
                  AllWorkersDone(w.tid);
              }
            };
            worker.RunWorkerAsync();
          }
        }

        void WorkerDone(int tid, int count)
        {
            Console.WriteLine("- tid: {0} Worker Done! count={1}",tid, 
count);
        }
        void AllWorkersDone(int tid)
        {
            BeepDone();
            Console.WriteLine("- tid: {0} All Workers Done!",tid);
        }
     }

     class Program
     {

        static void Main(string[] args)
        {
             WorkerJobs jobs = new WorkerJobs();

             Console.WriteLine("- Press ESCAPE to Exit");

             jobs.RunWorkers(5);

             while (true)
             {
               Thread.Sleep(50);
               if (Console.KeyAvailable &&
                  Console.ReadKey().Key == ConsoleKey.Escape) {
                  break;
               }
             }

        }
     }
}

-- 
HLS
0
Hector
6/2/2010 5:31:27 PM
Peter Duniho wrote:

>> Overall, from a software engineering standpoint, avoid thread designs 
>> based on time syncing and avoid using the common resource such as loop 
>> limit as the watch variable here.
> 
> Again, there is nothing in my code that relies on "time synching".  The 
> call to Thread.Sleep() is simply to simulate the worker thread doing 
> something.  The code will work regardless of the time each worker thread 
> spends doing work.


The point is that a little testing yourself would of shown that the 
using the count variable was not a good idea.

I naturally saw it even for I tried it to prove it was wrong because 
as you indicated, in the world real there would be "real work" not the 
poor man's sleep (which isn't any kind of simulated work whatsoever). 
This is common mistake in thread designs.

>> Two simple solutions - set the thread count outside the loop, or first 
>> prepare the threads, much like a "Suspended" concept and then start it 
>> after the preparation.
> 
> Neither of those are required.  They only add complexity, for no benefit.


But your example had a bug as I illustrated.

> I hope that you will go back and review the code example more carefully.


I did even before I posted. But only tried it because it was obvious 
there would a thread contention issue.


>  As I said at the outset, it is a good idea to become familiar with the 
> .NET-native techniques, and in this case that includes understanding 
> what BackgroundWorker actually does and how it works.


I doubt you even know which a common mistake you showed.  If you want 
to be respected, then show some respect yourself.

> In particular, knowing that the BackgroundWorker events, except for 
> DoWork, always get raised on the same thread that created the 
> BackgroundWorker instance (assuming that thread is one with a 
> SynchronizationContext, such as a normal, Forms GUI thread) is critical 
> in understanding why the code example I posted is correct.


You see, you assumed that I was naive about thread, GUI designs or 
designs in general  I seriously doubt you can match my expertise in 
this area. But that wasn't even the question - how GUI are blocks or 
not.  Yet, to show a solution, an able one, you did what experts 
consider a common mistake in thread design 101.

> Without that understanding, one might get distracted nit-picking aspects 
> of the code that don't have anything to do with the actual example, and 
> making incorrect statements about why one believes the code doesn't work 
> as posted.


Well, the fact was my statements are 100% correct and on the money, 
and I am following up for the archives, just in case someone needs 
something similar and uses your posted code as a framework.

You need to focus on what the questions and DO NOT PREASSUME too much 
into what a poster knows or doesn't.

Thanks for your comments.

-- 
HLS
0
Hector
6/2/2010 11:07:01 PM
Hector Santos wrote:
> [...]
>> Hector, you have completely missed the point of the code example, both 
>> in terms of what things in the code example are important, and in 
>> comprehending how the example actually works.
> 
> Really?  I think you are assuming too to be saying that.

I'm not assuming anything.  I'm just looking at your replies.

> [...]
> Its an important concept to not mix up SLEEP with ACTUAL THREAD WORK 
> when it come to system stabilization.

Sure, but there's nothing about my example that does that

> [...]
>> It would have been nice if you'd actually tried adding that code 
>> yourself.  Had you done so, you would have seen that it has no effect 
>> on the outcome of the code, other than to delay it of course.
> 
> 
> I did.  This following illustrates the contention issue with count as I 
> described.

No, it doesn't.  I stated several times that the BackgroundWorker 
depends on a GUI thread (actually, any thread with a 
SynchronizationContext, but in practice this is almost always a GUI thread).

Your example is a console application and as such is completely 
irrelevant to my code example and my comments.

Pete
0
Peter
6/3/2010 5:14:48 AM
Hector Santos wrote:
> The point is that a little testing yourself would of shown that the 
> using the count variable was not a good idea.

Please go back and read my posts more carefully.  You are not paying 
attention.

> I naturally saw it even for I tried it to prove it was wrong because as 
> you indicated, in the world real there would be "real work" not the poor 
> man's sleep (which isn't any kind of simulated work whatsoever). This is 
> common mistake in thread designs.

There's nothing about the call to Thread.Sleep() in my code example that 
has anything to do with the correctness of the code.  You can put 
anything you want in the DoWork event handler, and the code works just 
as well.

> But your example had a bug as I illustrated.

There is no bug in my example.

>> I hope that you will go back and review the code example more carefully.
> 
> I did even before I posted. But only tried it because it was obvious 
> there would a thread contention issue.

It is clear that you still have not sufficiently reviewed my posts.  You 
still misunderstand the point of the code example.

> I doubt you even know which a common mistake you showed.  If you want to 
> be respected, then show some respect yourself.

There is no mistake in my code.  It works fine in the context in which 
it's intended to be used.

>> In particular, knowing that the BackgroundWorker events, except for 
>> DoWork, always get raised on the same thread that created the 
>> BackgroundWorker instance (assuming that thread is one with a 
>> SynchronizationContext, such as a normal, Forms GUI thread) is 
>> critical in understanding why the code example I posted is correct.
> 
> You see, you assumed that I was naive about thread, GUI designs or 
> designs in general  

I made no such assumption.  I made an _observation_ that you have failed 
(and still continue to fail) to read my posts carefully enough to 
understand the point of the code example.

> I seriously doubt you can match my expertise in this 
> area. 

I'm not interested in a pissing match.  You go do that on your own.  All 
of my statements are strictly about factual matters that can be easily 
resolved simply by running the code.

But: you do need to pay attention.  Until you do so, you will not have 
any idea what I'm talking about.

Pete
0
Peter
6/3/2010 5:19:18 AM
Peter Duniho wrote:


>> But your example had a bug as I illustrated.
> 
> There is no bug in my example.


You're in denial.  I appreciate your input, but anyone worth his salt 
will see that that using a loop limit variable with internal local 
scope change is asking for trouble and would be contention in a real 
application using that piece of code. Sleep or not sleep, I saw it 
immediately.  Its extremely common to see that sort of thing with 
inexperienced developers in thread designs - ON ANY SYSTEM.  But with 
that latter point, I gave you benefit of the doubt thinking maybe the 
..NET compiler translated it as a constant, after all, it is a p-code 
compiler.  That was not the case here and the simply injecting of one 
line sleep (your idea of simulated "work" when here is no work at all) 
proves the case. When there is real work, you have your classic 
contention issues creeping up. That could of been anything.

I'll leave it at that.

-- 
HLS
0
Hector
6/3/2010 6:19:31 AM
Hector Santos wrote:
> Peter Duniho wrote:
> 
> 
>>> But your example had a bug as I illustrated.
>>
>> There is no bug in my example.
> 
> You're in denial.

You are wearing blinders.

> I appreciate your input, but anyone worth his salt 
> will see that that using a loop limit variable with internal local scope 
> change is asking for trouble and would be contention in a real 
> application using that piece of code. 

I have explained numerous times why that is not the case.

> Sleep or not sleep, I saw it immediately. [...]

You saw what you wanted to see, because you apparently care more about 
your criticism of me than technical accuracy.

If and when you ever go back and read my posts with the care they 
deserve, you will see how you are mistaken about your assessment of the 
code.

Pete
0
Peter
6/3/2010 6:49:29 AM
Peter Duniho wrote:

> Hector Santos wrote:


>> I appreciate your input, but anyone worth his salt will see that that 
>> using a loop limit variable with internal local scope change is asking 
>> for trouble and would be contention in a real application using that 
>> piece of code. 
> 
> I have explained numerous times why that is not the case.


And I explained three times now that you produced a bad example of 
thread synchronization.

>> Sleep or not sleep, I saw it immediately. [...]
> 
> You saw what you wanted to see, because you apparently care more about 
> your criticism of me than technical accuracy.


Exactly!

But if I am critical of you, it is your attitude to believe everyone 
is naive to extend and provide information that wasn't required. 
Again, all you showed here was the anonymous function - thats it!! 
Everything else was already known since the annals of preempted OSes!

> If and when you ever go back and read my posts with the care they 
> deserve, you will see how you are mistaken about your assessment of the 
> code.

Peter you said nothing but what you wanted to point out believing it 
was important, yet it was trivial to the question.  It added nothing 
beyond extracting two things only:

    - Your example of using anonymous functions here, which was good,
    - but nonetheless, also YOUR BUG!

And that was simply by eyeballing it and then verifying what would 
easly BREAK IT - and yet you went on a MAJOR ASSUMPTION that I didn't 
try your code, and you went on with that incorrect assumption.  The 
fact is you got a BUG  and you should be MAN enough to admit.

Everything else was trivial information which was (2nd time I told you 
this) was not being asked for.  You need to stop that. Do it with 
others, not with me. The other fellas were to the point in replies. 
You acting like everyone here is stupid.  What you indicated was 
nothing new NOR what was asked for. You need to stop that.

-- 
HLS
0
Hector
6/3/2010 11:10:34 AM
Hector Santos wrote:
> [...] The fact is you
> got a BUG  and you should be MAN enough to admit.

You can claim there's a bug until you're blue in the face, it still 
won't make it true.  You have not, and cannot, demonstrate the code I 
posted breaking in the context in which I specifically stated it was 
intended to be used.

Unfortunately, your ego prevents you from actually _reading_ what has 
been written.  Which is especially ironic, considering your "you should 
be MAN enough" comment.

Look at the facts.  Not your ego-driven bias.

Pete
0
Peter
6/3/2010 3:25:02 PM
On 6/3/2010 6:10 AM, Hector Santos wrote:
> And that was simply by eyeballing it and then verifying what would 
> easly BREAK IT - and yet you went on a MAJOR ASSUMPTION that I didn't 
> try your code, and you went on with that incorrect assumption.  The 
> fact is you got a BUG  and you should be MAN enough to admit.
>
I may regret this, but I'm going to stick my neck into this, as honestly 
I don't think either one of you is completely understanding the other 
:)  Hopefully I pull my neck back before I get it chopped off!

Hector - I think Peter's point is that yes, you came up with a situation 
where Peter's code does not work.  However, the situation is a case 
where it was NEVER intended to work.  You created the "bug" in a console 
application - the BackgroundWorker (to my knowledge) is designed solely 
to function within a Windows Forms application (maybe WPF?? Not sure on 
that one - I'll just stick with Windows Forms since you used 
Application.DoEvents() in your initial example).

The threading behaves VERY differently between the two environments.  In 
a Windows Forms environment, as your original code snippet suggests you 
are with the Application.DoEvents call, the 
BackgroundWorker.RunWorkerCompleted event is guaranteed to ONLY execute 
on the UI thread, and thus by definition can only be executed one at a 
time.  Since, at the end of Peter's post, he indicated that his sample 
assumes "RunWorkers" is ALSO on the UI thread, that means that 
RunWorkers itself will have to complete prior to any invocations of the 
RunWorkerCompleted occurring.  So, the only place "count" ever gets 
modified (or accessed, assuming DoWork does not also access it), is from 
the UI thread itself, which ensures there is no 
race-condition/contention issues.  That negates the need to pull out a 
separate variable "threadCount" since "count" cannot, given that code 
sample, be modified prematurely.

If RunWorkerCompleted is executed off the UI thread (or, ultimately I 
guess more importantly the thread which executed RunWorkers), then yes, 
the concerns you brought up are valid.  However, the entire purpose of 
BackgroundWorker is to get around that problem in a UI environment.

If you take the code sample outside the context they are given, sure, 
they can break - but that is true about most (all?) code :)

-Adam

0
Adam
6/3/2010 10:53:37 PM
Adam Clauss wrote:
> On 6/3/2010 6:10 AM, Hector Santos wrote:
>> And that was simply by eyeballing it and then verifying what would 
>> easly BREAK IT - and yet you went on a MAJOR ASSUMPTION that I didn't 
>> try your code, and you went on with that incorrect assumption.  The 
>> fact is you got a BUG  and you should be MAN enough to admit.
>>
> I may regret this, but I'm going to stick my neck into this, as honestly 
> I don't think either one of you is completely understanding the other 
> :)  Hopefully I pull my neck back before I get it chopped off!

I've no plans to do so.  :)

Still, you promised to point out how I've misunderstood Hector, but I 
didn't see anything in your post to point that out.  If I have, an 
independent observer such as yourself might have just the insight that 
would be useful to me to understand that.

As for what you did write…

> Hector - I think Peter's point is that yes, you came up with a situation 
> where Peter's code does not work.  However, the situation is a case 
> where it was NEVER intended to work.  You created the "bug" in a console 
> application - the BackgroundWorker (to my knowledge) is designed solely 
> to function within a Windows Forms application (maybe WPF?? Not sure on 
> that one - I'll just stick with Windows Forms since you used 
> Application.DoEvents() in your initial example).

Yes, you have understood my point correctly.  The original post and the 
use of BackgroundWorker all suggest a GUI context, and thus the capacity 
to take advantage of BackgroundWorker's features.

It's useful to note that BackgroundWorker will work in _any_ thread 
where there's a marshaling SynchronizationContext.  That is, the default 
SynchronizationContext doesn't actually marshal delegate invocations 
from one thread to another, but the SynchronizationContext found in a 
thread where Application.Run is running, or a WPF dispatcher is running, 
will do that.

So by default, BackgroundWorker provides the full functionality of its 
features in either a Forms or WPF application, provided it's created in 
a GUI thread in that application.  Furthermore, it is possible to write 
one's own SynchronizationContext class that works in other contexts. 
The important thing is that a SynchronizationContext is available for 
BackgroundWorker to use that will marshal delegate invocations onto the 
thread that created the BackgroundWorker.  It doesn't have to be a 
Forms, or even WPF, application.

> The threading behaves VERY differently between the two environments.  In 
> a Windows Forms environment, as your original code snippet suggests you 
> are with the Application.DoEvents call, the 
> BackgroundWorker.RunWorkerCompleted event is guaranteed to ONLY execute 
> on the UI thread, and thus by definition can only be executed one at a 
> time.  Since, at the end of Peter's post, he indicated that his sample 
> assumes "RunWorkers" is ALSO on the UI thread, that means that 
> RunWorkers itself will have to complete prior to any invocations of the 
> RunWorkerCompleted occurring.  So, the only place "count" ever gets 
> modified (or accessed, assuming DoWork does not also access it), is from 
> the UI thread itself, which ensures there is no 
> race-condition/contention issues.  That negates the need to pull out a 
> separate variable "threadCount" since "count" cannot, given that code 
> sample, be modified prematurely.

That is all exactly correct.

> If RunWorkerCompleted is executed off the UI thread (or, ultimately I 
> guess more importantly the thread which executed RunWorkers), then yes, 
> the concerns you brought up are valid.  However, the entire purpose of 
> BackgroundWorker is to get around that problem in a UI environment.

Exactly.  There's hardly any point in using BackgroundWorker where the 
BackgroundWorker instance isn't created in a thread where the 
SynchronizationContext stuff will work.  And since the original code 
example called Application.DoEvents(), it's safe to assume that the 
context is in fact a Forms application where the BackgroundWorker 
instances are created in the GUI thread (there's no need to call 
Application.DoEvents() if you're not executing in the main GUI thread 
and blocking it).

Finally, see below for a WPF example that incorporates the code I posted 
in a full application.

To Hector: you will find that it is not possible to cause the code to 
fail to correctly manage the value of the "count" variable without 
completely changing the nature of the code example (you can break any 
code if you just ignore the preconditions set for the use of that code). 
  In particular, it does not matter how many workers you create or what 
the DoWork event handler does, the code will work fine.

> If you take the code sample outside the context they are given, sure, 
> they can break - but that is true about most (all?) code :)

Exactly.

Pete

MainWindow.xaml:
<Window x:Class="TestThreadCounter.MainWindow"
         xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
         xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
         Title="MainWindow" Height="350" Width="525">
     <Grid>
         <Button Content="Run Threads" Height="23" 
HorizontalAlignment="Left" Margin="12,12,0,0" Name="button1" 
VerticalAlignment="Top" Width="114" Click="button1_Click" />
     </Grid>
</Window>


MainWindow.xaml.cs:
using System;
using System.Windows;
using System.ComponentModel;

namespace TestThreadCounter
{
     /// <summary>
     /// Interaction logic for MainWindow.xaml
     /// </summary>
     public partial class MainWindow : Window
     {
         public MainWindow()
         {
             InitializeComponent();
         }

         private void button1_Click(object sender, RoutedEventArgs e)
         {
             RunWorkers(100);
         }

         private void RunWorkers(int count)
         {
             string originalText = button1.Content.ToString();

             button1.IsEnabled = false;

             for (int i = 0; i < count; i++)
             {
                 int delay = i * 25;
                 BackgroundWorker worker = new BackgroundWorker();

                 worker.DoWork += (sender, e) =>
                     {
                         DateTime dtEnd = DateTime.Now + new TimeSpan(0, 
0, 0, 0, delay);

                         while (DateTime.Now < dtEnd)
                         {
                             //Thread.Sleep(1);
                         }
                     };

                 worker.RunWorkerCompleted += (sender, e) =>
                     {
                         if (--count > 0)
                         {
                             UpdateButton(count);
                         }
                         else
                         {
                             AllWorkersDone(originalText);
                         }
                     };

                 worker.RunWorkerAsync();
                 UpdateButton(i);
             }
         }

         private void UpdateButton(int count)
         {
             button1.Content = string.Format("{0} worker{1} left", 
count.ToString(), count > 1 ? "s" : "");
         }

         private void AllWorkersDone(string originalText)
         {
             button1.Content = originalText;
             button1.IsEnabled = true;
         }
     }
}
0
Peter
6/4/2010 3:35:02 AM
On 6/3/2010 10:35 PM, Peter Duniho wrote:
> Still, you promised to point out how I've misunderstood Hector, but I 
> didn't see anything in your post to point that out.  If I have, an 
> independent observer such as yourself might have just the insight that 
> would be useful to me to understand that.

Hehe, fair enough - I did forget to go down that path.  Got down into 
the technical details of the issue and hit send when I was done with them :)

Not so much that you were misunderstanding him, but maybe not making it 
as easy for him to understand you.  I had to jump back and forth quite a 
bit between posts trying to connect all the dots.  Part of that may 
simply be the inline quoting response.  The various pieces of important 
and relevant information get spread out across several different 
places.  That was what I hoped to accomplish by my "block" reply - 
consolidating all of the information into a single place.

Normally I think the inline responses are a good way to address 
different points of a topic, but this time it made it harder for some 
reason...

Just my thoughts...

-Adam
0
Adam
6/4/2010 1:58:24 PM
On 6/3/2010 5:25 PM, Peter Duniho wrote:
> Hector Santos wrote:
>> [...] The fact is you
>> got a BUG  and you should be MAN enough to admit.
> 
> You can claim there's a bug until you're blue in the face, it still
> won't make it true.  You have not, and cannot, demonstrate the code I
> posted breaking in the context in which I specifically stated it was
> intended to be used.

Hector believes this would be a demonstration: in the first iteration of
the main loop first thread is created, its function set, and spawned to
run. BUT, when its time for second iteration first thread might already
be finished. This in turn decrements count, which reduces the number of
threads that would be spawned.

In C++ world this would be the case because RunWorkerCompleted would run
from spawned thread's context, but in C# world it will be run from main
thread's context, AFTER all threads are already spawned.

So, really, there's no bug here, AFAICS.
0
UTF
6/4/2010 2:45:07 PM
Mihajlo Cvetanović wrote:
> On 6/3/2010 5:25 PM, Peter Duniho wrote:
>> Hector Santos wrote:
>>> [...] The fact is you
>>> got a BUG  and you should be MAN enough to admit.
>> You can claim there's a bug until you're blue in the face, it still
>> won't make it true.  You have not, and cannot, demonstrate the code I
>> posted breaking in the context in which I specifically stated it was
>> intended to be used.
> 
> Hector believes this would be a demonstration: in the first iteration of
> the main loop first thread is created, its function set, and spawned to
> run. BUT, when its time for second iteration first thread might already
> be finished. This in turn decrements count, which reduces the number of
> threads that would be spawned.

In the wrong context, this is indeed a potential outcome.  That's why I 
was so specific about the context in which the code I posted is intended 
to be used.

> In C++ world this would be the case because RunWorkerCompleted would run
> from spawned thread's context, but in C# world it will be run from main
> thread's context, AFTER all threads are already spawned.

It's not so much a language-dependent behavior, but a run-time 
context-dependent behavior.  In particular, as I've pointed out 
previously and as Adam's reiterated, the important thing is whether 
there is a way for BackgroundWorker to do what it's designed to do (i.e. 
whether there's a SynchronizationContext from the Forms or WPF APIs for 
the thread in which the BackgroundWorker instance was created).

Assuming one is writing managed code, then it does not matter whether 
the code is written in C++ or C#; as long as the BackgroundWorker is 
created in the GUI thread for a Forms or WPF application, the code I 
posted works fine.

If one is not writing managed code, then all of this is moot because the 
code I posted won't compile.

> So, really, there's no bug here, AFAICS.

That is correct.  There's no bug here.  Thank you for your independent 
confirmation of that!

Pete
0
Peter
6/4/2010 3:24:45 PM
On 6/3/2010 10:35 PM, Peter Duniho wrote:
> It's useful to note that BackgroundWorker will work in _any_ thread 
> where there's a marshaling SynchronizationContext.  That is, the 
> default SynchronizationContext doesn't actually marshal delegate 
> invocations from one thread to another, but the SynchronizationContext 
> found in a thread where Application.Run is running, or a WPF 
> dispatcher is running, will do that.
>
> So by default, BackgroundWorker provides the full functionality of its 
> features in either a Forms or WPF application, provided it's created 
> in a GUI thread in that application.  Furthermore, it is possible to 
> write one's own SynchronizationContext class that works in other 
> contexts. The important thing is that a SynchronizationContext is 
> available for BackgroundWorker to use that will marshal delegate 
> invocations onto the thread that created the BackgroundWorker.  It 
> doesn't have to be a Forms, or even WPF, application.

As a side note - thank you for this little explanation... I've had more 
than a couple cases come up where I was dealing with a 3rd party API 
which, by their requirement, I could only create it's objects and make 
calls on those objects from a single thread (no UI even involved in 
these situations).

I ended up creating my own object which I closely related to a 
"ThreadPool" that only had 1 thread in it processing items (I did not 
want to make use / alter the system thread pool).  I have no idea what 
would have been involved in writing "one's own SynchronizationContext", 
but I'm wondering if that's basically what I did, or if trying to do so 
would have simplified anything...

Anyway, gave me something to go think about and read up more on.

Thanks,
Adam
0
Adam
6/4/2010 6:14:36 PM
Adam Clauss wrote:
> As a side note - thank you for this little explanation... I've had more 
> than a couple cases come up where I was dealing with a 3rd party API 
> which, by their requirement, I could only create it's objects and make 
> calls on those objects from a single thread (no UI even involved in 
> these situations).
> 
> I ended up creating my own object which I closely related to a 
> "ThreadPool" that only had 1 thread in it processing items (I did not 
> want to make use / alter the system thread pool).  I have no idea what 
> would have been involved in writing "one's own SynchronizationContext", 
> but I'm wondering if that's basically what I did, or if trying to do so 
> would have simplified anything...

Yes, the innards of a custom SynchronizationContext is likely to look a 
lot like a thread pool with one thread.

The Forms version actually uses the thread's message queue, and I don't 
actually know how the WPF one works.  But those are special cases meant 
to deal with other requirements those APIs have.  A custom one usually 
wouldn't be bound by those issues and could just use a regular work 
queue with a single consuming thread.

> Anyway, gave me something to go think about and read up more on.

I recall a discussion with someone else several months ago (maybe even a 
year or more…I don't recall for sure), in which they wanted to write 
their own SynchronizationContext.

It should not be _too_ involved, and if I recall correctly, they were 
able to get theirs working.  I think they might have even posted the 
source code here.

If you're interested and if after looking you aren't able to find the 
thread I'm talking about, follow up here and I'll take a look myself.

Pete
0
Peter
6/5/2010 3:31:04 AM
Reply:

Similar Artilces:

Move database from C to D
Can anyone give me direction on how to move the rms database from drive C todrive D? I'm using RMS 2.0. Thanks in advance. -- Randy Manchester Here are some instructions I made for a friend. Please note that these instructions were made on a computer where I didn't have access to an SQL Database, so some of the directories could be wrong. If you need more detailed instructions, e-mail my gmail.com account: natesawyer3. ~Nate 1. Download the appropriate SQL Management Studio Express for your operating system, and install it on the Computer with the database on it. [Link] 2. Open ...

Problem with blocking of main thread with other thread
I have a problem with blocking of main thread: My application contains an interpreter and I need to write a debugger for it. The mainframe creates a thread that is interpreting instructions. When I need to break execution of instruction thread, I use WaitForSingleObject(m_WaitEventHandle, INFINITE); in the interpreter thread. Everything works fine until the window is opened from the interpreter. Then the mainframe freezes. When I break execution in VC the call stack for interpreter thread shows: � NTDLL! � KERNEL32! � CDebugManager::CheckBreakpoints() � CInterpreterThread::Run() � _Afx...

Where is my thread?
I posted a question about "Search for a value in multi-dimensionla array" an hour ago; where did that go? On 5/17/2010 17:38, Rick wrote: > I posted a question about "Search for a value in multi-dimensionla array" an > hour ago; where did that go? If you mean the one beginning with "Seach", posted almost half an hour before this one, it is there. :) On 5/17/2010 11:51 AM, Jackie wrote: > On 5/17/2010 17:38, Rick wrote: >> I posted a question about "Search for a value in multi-dimensionla >> array" an >> hour ag...

Qry showing AutoNumber as A. B or C.
Hi; Using a Select Qry to display the ID Autonumber of an open Form. IDNumber: [Forms]![frmCustomers]![txtCustomerID] Note: txtCustomerID is an Alias for CustomerID. When the Qry is run it shows the ID number as A, B or C. Although it shows as a number on the Frm. And it will continue to add Alpha letters if the User adds new records. Even tried adding a control with its source as Name: FedFromID Record Source=txtCustomerID and changing IDNumber: [Forms]![frmCustomers]![FedFromID] Would someone be so kind to point me in the correct direction to correct this. Thank You for taking the ...

Simple Thread
I have created a thread in my MFC Dialog based application, in the thread function i want to have access to a user interface control that is attached to the main dialog. How can I do it? Regards, Mystique Mystique wrote: > I have created a thread in my MFC Dialog based application, in the thread > function i want to have access to a user interface control that is attached > to the main dialog. > How can I do it? > > Regards, > Mystique > > Indirectly, by posting a message to the main thread asking it to update the control. http://www.mvps.org/vcfaq/mfc/12.ht...

Diaglog/Threading Data Exchange Question
Greetings, I have learned a lot from all of you, and I hope to over come my latest road block. I have a smal IRC Chat client I am making. I have a Dialog Box with Control and I use a worker thread for connecting to IRC - That Thread will update controls on the Dialog by sending PostMessages. Now my problem is in the ListBox Control that I have extended to do popup menu with various commands. I need to be able to read that controls methods from within the Thread. so I need to do this from within my IRC Socket thread: (code not exact - pseudo code) CListBoxEx myUsers; //Defined in my ...

Need Help with Busy Dialog Thread
my application would perform a task. I want to stop the user from using the application's GUI untill the the BG task is finished. At first using Modal Dlg did not do the trick as every one now (apart from me) the the CDialog::DoModal() function has to return some how. So, I made a bit of research on the net and found a trick to display the Dialog using CWinThread derived class without stoping the main app window for executing the background task as follows: (1) In your header file define a CWinThread-derived class... class CDialogThread : public CWinThread { DECLARE_DYNCREATE(CDial...

Killing thread from outside thread in MFC App
Hi, Thanks to all those who offered advise on my last query. I successfully used the worker thread method to give control back to the dialog box whilst background processing was being carried out. The issue I have now is closing that thread externally. The method I've used to create the thread uses a volatile boolean variable. Whilever it is set to TRUE, the thread remains alive. However, when I set the variable to FALSE from the calling process (user wants to end processing), it has no effect. The thread continues to run. I thought that declaring the variable as 'volatile'...

Outlook 2000 C++ Error
When I first open Outlook I get a Microsoft Visual C++ Runtime Library Runtime Error Program: c:\\progra~1\micros~2\office\outlook.exe This ap[plication has requested the Runtime to be terminated in an unusual way. Please contact the applications support team for more information. When I click OK I get about 12 more different errors, and then Outlook closes. I can then open it and it works. CAN ANYONE DECHIPER THIS? I have tried uninstalling/reinstalling Office, updating all patches and SPs, Erase2000 won't open with XP (Home)....I am at a lose. ...

To Thread or not to thread
I am using a CRecordset object to retrieve data from a remote server. The time to retrieve the data is highly variable because of network traffic etc etc etc and has varied from a few ms to almost a minute. Question: Is it a good practice to use a worker thread to handle the database exchange to avoid having my main thread block for long periods of time? I assume that I would let the exchange timeout and then check the return status and a global variable to determine if it should keep trying until it returned data ( might be null but that's ok). Ron H. Ron, While it may be a tin...

Anyone care to offer advice for my Client / Server threading model
I'm a bit of a sockets newbie and not too sure what the established ways of handling CAsyncSockets are. I need to handle two way comms between two or more handheld pcs and a server. WIth the server I've got: 1 Thread polling for new connections 1 Thread per client connection. The client thread is stuck in a loop called from CWinThread::InitInstance and sits and calls the CAsyncSocket::Receive function until something arrives. It uses peekmessage and postmessage in this loop to see if the app wants me to send anything to the client. This is working erratically though - peekmessage know...

multi-threaded control not destroyed on exiting the page?
I have created an ActiveX control (subclassing COleControl) which uses the afxRegFreeThreading model, and I have a small sample web page which inserts the control using an <object> tag. I noticed that when my page places the control inside the <head> tag, the control's destructor is called when my browser goes to a different page. But if the control is inside the <body> tag, the destructor is not called when I leave the page. The control's destructor is eventually called when I exit my browser, but I fear that my control is continuing to occupy system resources unt...

Threads in MFC
Hi to all... I've made a multithreaded Application (with MFC of course) and it works well on some PC, but in others PC's with the same OS (Win2000SP4) it throws "access Violation" immediatly just when a thread starts. (No matter which one... just the first). I've supposed it was some lib missing, and I've installed VC6... it didn't solve anything. any suggestion? I had a similar problem when I didn't realize I was trying to distribute a DEBUG version of the program. Otherwise, can you post a code snippet? On Mon, 19 Apr 2004 16:55:16 +0200, Nicola Bam...

Can I use MSComm in C++ console App?? How???
I am tring to write a console app that interfaces with the serial port. I would like to use MSComm if possible. I pretty much know how to do it using an MFC or a dialog app but can't see how to do it for the console. MSCOMM is so much more difficult to use than raw serial port interfacing that it is not clear what value it adds. joe On 19 Oct 2005 16:28:10 -0700, "salsipius" <salsipius@salsipius.com> wrote: >I am tring to write a console app that interfaces with the serial port. >I would like to use MSComm if possible. I pretty much know how to do it >using...

MAD monitoring thread?
I have Exchange 2000 running on a Win2K Server. I have a trust to an NT4 domain with an Exchange 5.5 Server. Both are in the same site and my goal is to move the mailboxes and whatnot to the Exchange 2000 box. So far, just getting 2000 to operate has been a problem. It's installed and running but my MS Exchange Info Store and MTA stacks won't start in the services. If I reboot, they start, but stop within a few minutes. I have errors in my application log for MSExchangeSA that say, "The MAD monitoring thread was unable to read its configuration from the DS." I have MSEx...

A thread within a thread...
Hi, If i create a thread within a thread, something like... void threadA(void lparam ) { ... (HANDLE)_beginthread(ThreadB,0,someotherlparam); ... // do more work _endthread(); // done } My question is what happens to the thread i created, (threadB), if it is not finished? Is it safe, good?, to stop threadA without waiting for threadB. Many thanks Sims There is no concept of "a thread within a thread". All threads are within a process, and they are all peers of each other. DO NOT use _beginthread in an MFC program. This is asking for trouble. An...

SEO and usability
Dear News Readers, I have a question about seo and usability for web site: 1. What should I prefered, to use blogger.com or my own blog? blogger.com is preformated, scalirbar - is a question, but most of contra is that- all user are not in my db, and I should import them 2. wenn I use my own blog, then I have all user in my db, but, the question is Rating(PR) of my blog is better or not vs. blogger.com I must subscribe my blog into blogger comunity and submission pages Please, tell me your opinion(pro and contra) about this thema. Best Ragards ===============...

Equivalent of Minus in Excel. Also Union, Intersect.
Dear experts, In excel, I have to find the differences between two sets of data. Just like your set theory from grade 9 . In one set, I have, say, A B C D E F In the other set, I have, D E F Set one, minus set two is: A B C I would like to put the results of the minus into a new column. In sql, you would just: Query1 minus Query2 But database is not an option here. The data is only in the spreadsheet. How can I do the same thing in excel? Related to this, would be: Union, and Intersect. Thanks Actually SQL is an option: http://www.erlandsendata.no/english/index.php?t=e...

why CStatic.m_hWnd not valid use realtime thread
Hi All I build an MFC app, and loadlibrary a dll which use high priority (realtime level ) threads for serial communication but after freelibrary the dll, some CStatic and CEdit objects not valid, their m_hWnd becomes to NULL How can I restore these CWnd objects? Is OS release them thanks, waiting online ...

A "C" in the middle of my chart
There is a "C" or "(" that is showing up in the middle of my Excel bar chart, and I don't know how to get rid of it. Any ideas? Thanks, Em Move the cursor slowly up to the character (it's a textbox) until the cursor changes to the four arrow icon, click once to select the textbox, and press Delete. It might be easier to select the textbox if you select the "Select Objects" button (looks like a cursor arrow) on the Drawing toolbar. - Jon ------- Jon Peltier, Microsoft Excel MVP Peltier Technical Services Tutorials and Custom Solutions http://Peltier...

threads #2
I have a server/client application that communicates using threads. The server class uses a while loop inside a thread to wait for new connections in accept state, like this: var a = new var( ); while( (server.Accept(connection)) ) { ...... ...... } I have declared a variable (var) right before this loop which uses memory. I want to free/delete this variable at the end of the while loop, but the control never reaches there. How can I make sure that this variable gets deleted before the server side exits? Thanks. Jessica Jessica Weiner wrote: > I have a server/client applicatio...

Outlook 2002
I use outlook 2002 on a Windows NT SP6a machine. While using outlook, i have noticed that sometimes the keys c, v, t and h stop working. however, i can use them in notepad. i can also use them in outlook if i put the caps lock on and use the shift key. if i restart outlook, the problem goes away. sometimes the problem goes away as well on its own without having to restart. any idea what is happening? language is set as english (Australia) ...

Destroy thread and Terminate thread
Hi, is there any difference between "Destroy thread and Terminate thread" regds vinay "Vinay" <v.sheel@mailcity.com> wrote in message news:uXR4ntHIEHA.2576@TK2MSFTNGP09.phx.gbl... > Hi, > is there any difference between > "Destroy thread and Terminate thread" > regds > > vinay > > A quote from the docs: "TerminateThread is a dangerous function that should only be used in the most extreme cases." destroyThread, on the other hand, deletes the thread object created by createThread. The thread should be terminated by some o...

How do I add a copyright (c) symbol to Auto Correct
My windows XP does not include the copyright symbol in auto correct. How do I add it to auto correct. Thanks. Hi Judy For XL2003 and earlier Tools>Options>Spelling>Autocorrect Options>Replace (c) With � For XL2007 Circular Office button>Excel Options>Proofing>Autocorrect Options>Replace (c) With � -- Regards Roger Govier "Judy Southwest" <Judy Southwest@discussions.microsoft.com> wrote in message news:38C2BE97-40B2-485F-97A2-1DD39E50F1FD@microsoft.com... > My windows XP does not include the copyright symbol in auto correct. > How ...

Start background thread when a UI button is clicked, and Update UI button from background thread
I was asked these questions during a technical interview: 1) When the user clicks on a button on the form and that invokes a lot of heavy-duty calculations, what would you do? My answer: I would use "BeginInvoke" to start a background worker thread to do the heavy-duty calculations, in order to avoid blocking the main UI thread. Then he asked, "What does 'BeginInvoke' do"? I said it was a .NET pattern to start a background thread from a UI thread. Did I get it right? 2) Why can't you simply update a button on the UI thread from a background ...