PC Review


Reply
Thread Tools Rate Thread

Anonymous methods, captured variables and the Thread Pool

 
 
Anthony Paul
Guest
Posts: n/a
 
      10th Apr 2009
Hello everyone,

I just ran into a problem today that I found rather weird but can't
think of a reason why it's occurring, so I'm putting it out here to
see if any gurus have a better understanding of what's going on.

I have a method that I use to facilitate asynchronous operations such
that it accepts two delegate parameters, one that gets executed by a
background thread via the ThreadPool and the other a delegate to call
on the UI thread once the background thread is done. Works great, no
problems, but then I ran into a situation where I wanted to execute
multiple work delegates instead of just one, and once they are all
done only then would the UI delegate get called. So I did that, and
here's my modified method :

protected void DoAsyncStuff(ThreadStart[] workDelegates, ThreadStart
uiDelegate)
{
int workers = workDelegates.Length;

foreach (ThreadStart workDelegate in workDelegates)
{
ThreadPool.QueueUserWorkItem
(
(WaitCallback)delegate
{
workDelegate();
if (uiDelegate != null)
{
if
(Interlocked.Decrement(ref workers) == 0)
{

Dispatcher.BeginInvoke
(

(ThreadStart) delegate
{

uiDelegate();
},

System.Windows.Threading.DispatcherPriority.Normal
);
}
}
},
null
);
}
}

Now here's my method that uses it :

private void MyMethod()
{
int result1;
int result2;
DoAsyncStuff
(
new Delegate[]
{
delegate
{
result1 =
Model.GetRandomNumber();
},
delegate
{
result2 =
Model.GetRandomNumber();
}
},
delegate
{
// do something here with the
results
}
);
}

Everything executes fine, but when both work delegates have finished
executing and the UI delegate executes, result2 is the only one that
has a value. result1 didn't get updated. If I reverse the order,
again, the first delegate doesn't seem to return a value, but the
second one does. Does anyone understand what's going on here?

Regards,

Anthony
 
Reply With Quote
 
 
 
 
Anthony Paul
Guest
Posts: n/a
 
      10th Apr 2009
Ahhh yes of course! I'm such an idiot, I know all about the scope of
captured variables (as you can see in the method calling DoAsyncStuff)
but *completely* missed the boat in the DoAsyncStuff method. Thank
you, Pete, for pointing out what should have been obvious to me!
Doh!

On Apr 10, 2:55*pm, "Peter Duniho" <NpOeStPe...@nnowslpianmk.com>
wrote:
> On Fri, 10 Apr 2009 11:32:44 -0700, Anthony Paul <anthonypa...@gmail.com>*
> wrote:
>
> > [...]
> > Everything executes fine, but when both work delegates have finished
> > executing and the UI delegate executes, result2 is the only one that
> > has a value. result1 didn't get updated. If I reverse the order,
> > again, the first delegate doesn't seem to return a value, but the
> > second one does. Does anyone understand what's going on here?

>
> Yes. *You've made the classic error in dealing with captured variables:*
> reusing a loop variable for each delegate instance, rather than providing*
> a new copy of the loop variable for each.
>
> By the time your threads get to run, the loop has finished, and the loop *
> variable is equal to the last value it had. *Thus, both threads use the*
> same value. *In this case, the value is a delegate itself, and so that *
> last delegate is the only one to execute, and it executes twice (in your *
> example, because there are two elements in the array).
>
> The solution is to copy the loop variable to a local variable inside the *
> loop block, so that each delegate instance gets its own copy:
>
> * * *foreach (ThreadStart workDelegate in workDelegates)
> * * *{
> * * * * *ThreadStart workCaptured = workDelegate;
>
> * * * * *ThreadPool.QueueUserWorkItem(
> * * * * * * *delegate()
> * * * * * * *{
> * * * * * * * * *workCaptured();
> * * * * * * * * *if (uiDelegate != null)
> * * * * * * * * *{
> * * * * * * * * * * *// other stuff
> * * * * * * * * *}
> * * * * * * *}, null);
> * * *}
>
> And please, next time ease off the tab-stops. *The indentation in your *
> posted code was a bit ridiculous. *
>
> 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
Anonymous methods, ThreadPool, and captured variables Anthony Paul Microsoft Dot NET 3 14th Apr 2009 09:50 AM
Anonymous Delegates, captured variables and ThreadStart ktrvnbq02@sneakemail.com Microsoft C# .NET 1 13th Jun 2008 05:35 PM
Is there any problem to use anonymous methods under multi-thread? Dancefire Microsoft Dot NET Framework 3 12th Nov 2007 09:33 AM
How to know when a thread in a thread pool has finished executing my workitem ? palaga Microsoft C# .NET 2 16th Mar 2005 04:12 PM
Thread-safe static methods/variables S Microsoft ASP .NET 1 26th Apr 2004 12:40 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 09:57 AM.