Hi,

Someone wrote me privately about this thread email chain expressing
questions about my previous remarks.   Presently, .NET is not designed to
safely and reliably interact with Windows Forms controls across thread
boundaries. To correct this deficiency, marshal any data or interactions
from the background thread to the same thread of the Windows Forms. One
option for accomplishing this is a delegate. For example, if you want to
update a GUI component from the BackgroundWorker's event handler, you need
to define a delegate with arguments mirroring the data to pass and use the
Form's Invoke method. Call Invoke with the delegate address and data—
marshalling.  The thread pool using ThreadPool.QueueUserWorkItem or joined
worker threads would operate on the server and respond back to the client.

The article "Safe Multithreading with the BackgroundWorker Component"
provides a better explanation than my previous emails.

http://www.codeguru.com/csharp/csharp/cs_syntax/threading/article.php/c10755/

HTH,
Kara


On 7/20/07, Ryan Heath <[EMAIL PROTECTED]> wrote:

No, the Set & Reset calls must be sync'ed too

Look at those two running threads using InterlockedBlah:
calls = 1
Thread A calls Set
Thread B calls Reset

Thread A : decr (calls is now 0)
Thread B : comp (calls == 0)
Thread B : evt.Reset
Thread A : evt.Set
Thread B : incr (calls is now 1)

now we have the event in a signaled state, while calls != 0. Thats is
a bug, the event must be signaled only when there a 0 calls.

// Ryan

On 7/20/07, Nassar, Anthony <[EMAIL PROTECTED]> wrote:
> Ryan, couldn't you just use the InterlockedBlah methods to save yourself
> from having to lock?
>
> -----Original Message-----
> From: Discussion of advanced .NET topics.
> [mailto:[EMAIL PROTECTED] On Behalf Of Ryan Heath
> Sent: Friday, July 20, 2007 4:37 AM
> To: [email protected]
> Subject: Re: [ADVANCED-DOTNET] Question about the right way to use
> BackGroundWorker
>
> I have added a simple class CountedEvent to your code [1] Now you do not
> have to burn the cpu waiting for all jobs to finish.
>
> Its interesting to see that RunWorkerCompleted is called after(!) all
> jobs have finished... This is due to that BackgroundWorker is designed
> to work in an UI environment. When no real UI response is needed the
> BackgroundWorker would not be my first choice for this kind of work. I
> supports Gregs suggestion to use QueueUserWorkItem, and perhaps in
> combination with CountedEvent.
>
> HTH
> // Ryan
>
> [1]
> using System;
> using System.Collections.Generic;
> using System.Text;
> using System.ComponentModel;
> using System.Threading;
> using System.Collections;
>
> namespace BackgroundWorkerDemo
> {
>    class CountedEvent
>        {
>          ManualResetEvent evt = new ManualResetEvent(true);
>          int calls = 0;
>
>          public void WaitOne()
>          {
>            evt.WaitOne();
>          }
>          public void Set()
>          {
>            lock( evt)
>                {
>                  calls--;
>              if ( calls == 0)
>                  {
>                    evt.Set();
>                  }
>                }
>          }
>          public void Reset()
>          {
>                lock( evt)
>                {
>                  if ( calls == 0)
>                  {
>                    evt.Reset();
>                  }
>                  calls++;
>                }
>          }
>        }
>
>   class Program
>   {
>       static void Main(string[] args)
>       {
>           DateTime start_time = DateTime.Now;
>
>           Console.WriteLine("Program starting");
>
>           //RunSyncVersion();
>           RunAsyncVersion();
>
>           DateTime end_time = DateTime.Now;
>
>           TimeSpan ts = end_time - start_time;
>
>           Console.WriteLine("Program completed. Duration={0} seconds.",
> ts.Seconds);
>           Console.Read();
>       }
>
>       //Synchronous version
>       static void RunSyncVersion()
>       {
>           for (int i = 0; i <= 10; i++)
>           {
>               LongRunningOperation(i);
>           }
>       }
>
>       //This version uses the async version
>       static void RunAsyncVersion()
>       {
>                        CountedEvent jobFinished = new CountedEvent();
>           ArrayList lstBGWs = new ArrayList();
>
>           for (int i = 0; i <= 10; i++)
>           {
>               BackgroundWorker worker = new BackgroundWorker();
>                                jobFinished.Reset();
>
>               worker.DoWork += new DoWorkEventHandler(worker_DoWork);
>
>               worker.RunWorkerCompleted += delegate(object sender,
> RunWorkerCompletedEventArgs e)
>                        {
>                                        jobFinished.Set();
>                        Console.WriteLine("Set called");
>                        };
>
>               lstBGWs.Add(worker);
>
>               worker.RunWorkerAsync(i);
>           }
>
>                        jobFinished.WaitOne();
>                        Console.WriteLine("exit");
>       }
>
>       static void worker_DoWork(object sender, DoWorkEventArgs e)
>       {
>           BackgroundWorker worker = sender as BackgroundWorker;
>
>           LongRunningOperation(Convert.ToInt32(e.Argument));
>       }
>
>       //Long running operation
>       private static void LongRunningOperation(int operation_number)
>       {
>           Console.WriteLine("Operation# {0} starting on Thread {1}",
> operation_number, Thread.CurrentThread.ManagedThreadId);
>           for (int i=0; i < 1000000000; i++)
>           {
>
>           }
>
>           Console.WriteLine("Finished operation# {0} on Thread {1}",
> operation_number, Thread.CurrentThread.ManagedThreadId);
>
>       }
>   }
> }
>
> ===================================
> This list is hosted by DevelopMentor(r)  http://www.develop.com
>
> View archives and manage your subscription(s) at
> http://discuss.develop.com
>
> ===================================
> This list is hosted by DevelopMentor(r)  http://www.develop.com
>
> View archives and manage your subscription(s) at
http://discuss.develop.com
>

===================================
This list is hosted by DevelopMentor(r)  http://www.develop.com

View archives and manage your subscription(s) at
http://discuss.develop.com


===================================
This list is hosted by DevelopMentor®  http://www.develop.com

View archives and manage your subscription(s) at http://discuss.develop.com

Reply via email to