PC Review


Reply
Thread Tools Rate Thread

Asynchronous Delegates always using same worker thread

 
 
Coot
Guest
Posts: n/a
 
      15th Apr 2004
I've been running many tests of the Asynchronous Delegate technique
and I find that although BeginInvoke() does queue the method delegate
onto a worker thread, it always does so on the _same_ thread. So if I
call BeginInvoke() three times in a row, the method delegates are
queued to the same thread and the second method doesn't begin until
the first method completes, and the third doesn't begin until the
second completes.

This occurs whether I detect completion through callback,
AsyncWaitHandle, or polling. It occurs no matter whether the delegate
refers to the same instance method or different instance methods.

The bottom line is that I don't get multi-threaded behavior, but only
two-threaded behavior.

I believe this is not the intended behavior. Has anyone else seen
this? Does anyone know why this is happening?

--
Dave Hein
 
Reply With Quote
 
 
 
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      15th Apr 2004
Not sure what you are exactly doing in your method, but this is the normal
behavior when:
1 - the method returns before it consumed it's CPU quota (this without
executing a blocking call) AND
2 - you run this on a single CPU machine.

Willy.


"Coot" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> I've been running many tests of the Asynchronous Delegate technique
> and I find that although BeginInvoke() does queue the method delegate
> onto a worker thread, it always does so on the _same_ thread. So if I
> call BeginInvoke() three times in a row, the method delegates are
> queued to the same thread and the second method doesn't begin until
> the first method completes, and the third doesn't begin until the
> second completes.
>
> This occurs whether I detect completion through callback,
> AsyncWaitHandle, or polling. It occurs no matter whether the delegate
> refers to the same instance method or different instance methods.
>
> The bottom line is that I don't get multi-threaded behavior, but only
> two-threaded behavior.
>
> I believe this is not the intended behavior. Has anyone else seen
> this? Does anyone know why this is happening?
>
> --
> Dave Hein



 
Reply With Quote
 
Coot
Guest
Posts: n/a
 
      16th Apr 2004
"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
> Not sure what you are exactly doing in your method, but this is the normal
> behavior when:
> 1 - the method returns before it consumed it's CPU quota (this without
> executing a blocking call) AND
> 2 - you run this on a single CPU machine.
>
> Willy.
>


Yes, it is a single CPU machine _BUT_ no the method doesn't return
that quickly.

Here is the method:

public int TestMethod( TimeSpan callDuration, out int threadId )
{
threadId = AppDomain.GetCurrentThreadId();

int myThreadId = threadId;
int count = 10;
TimeSpan subDuration = TimeSpan.FromTicks( callDuration.Ticks /
count );
Type t = this.GetType();
for (int i = 0; i < count; ++i)
{
Thread.Sleep( subDuration );
Console.WriteLine(
"[" + myThreadId.ToString() + "] "
+ t.FullName + ".TestMethod(): " + DateTime.Now.TimeOfDay + " "
+ i.ToString() );
}

return threadId;
}


I'm invoking it with call durations of 0.5 to 1.0 seconds.

The problem occurs if I create a delegate for this method and then use
the BeginInvoke() method of the delegate.

Note: I've also created another class that provides a threaded
implementation that calls that same method via a custom
BeginTestMethod() (and returns results through a custom
EndTestMethod()) -- when I create thread in my custom method I can get
a large number of these TestMethods() executing concurrently -- on my
single CPU box.

But using the async delegate and BeginInvoke(), all I can do is queue
multiple invocations, but they all end up executing, in sequence, on
the same worker thread. :-(

--
Dave Hein

[snip]
 
Reply With Quote
 
Willy Denoyette [MVP]
Guest
Posts: n/a
 
      16th Apr 2004

"Coot" <(E-Mail Removed)> wrote in message
news:(E-Mail Removed)...
> "Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message
> news:<(E-Mail Removed)>...
>> Not sure what you are exactly doing in your method, but this is the
>> normal
>> behavior when:
>> 1 - the method returns before it consumed it's CPU quota (this without
>> executing a blocking call) AND
>> 2 - you run this on a single CPU machine.
>>
>> Willy.
>>

>
> But using the async delegate and BeginInvoke(), all I can do is queue
> multiple invocations, but they all end up executing, in sequence, on
> the same worker thread. :-(
>
> --
> Dave Hein
>
> [snip]

Well, this code:

using System;
using System.Threading;
namespace Willys
{
class Tester
{
static void Main()
{
Target t = new Target();
t.SpawnEm();
}
}
}

public class Target {
public delegate int LaunchProc(TimeSpan ts, out int v);
public int TestMethod( TimeSpan callDuration, out int threadId )
{
threadId = AppDomain.GetCurrentThreadId();
int myThreadId = threadId;
int count = 10;
TimeSpan subDuration = TimeSpan.FromTicks( callDuration.Ticks /count );
Type t = this.GetType();
for (int i = 0; i < count; ++i)
{
Thread.Sleep( subDuration );
Console.WriteLine("[" + myThreadId.ToString() + "] "
+ t.FullName + ".TestMethod(): " + DateTime.Now.TimeOfDay + " "
+ i.ToString() );
}
return threadId;
}
public void SpawnEm() {
int count = 2;
IAsyncResult[] asr = new IAsyncResult[count];
int threadId = 0;
LaunchProc pfn = new LaunchProc(this.TestMethod);
for (int t = 0; t< count; t++) {
asr[t] = pfn.BeginInvoke(new TimeSpan(20000000),out threadId, null,
null);
}
foreach(IAsyncResult ar in asr)
{
pfn.EndInvoke(out threadId, ar);
Console.WriteLine("Thread [{0}] Done", threadId);
}
}
}

Gives this:
[2856] Target.TestMethod(): 19:03:39.0448656 0
[2856] Target.TestMethod(): 19:03:39.2451536 1
[2856] Target.TestMethod(): 19:03:39.4454416 2
[2976] Target.TestMethod(): 19:03:39.5455856 0
[2856] Target.TestMethod(): 19:03:39.6457296 3
[2976] Target.TestMethod(): 19:03:39.7458736 1
[2856] Target.TestMethod(): 19:03:39.8460176 4
[2976] Target.TestMethod(): 19:03:39.9461616 2
[2856] Target.TestMethod(): 19:03:40.0463056 5
[2976] Target.TestMethod(): 19:03:40.1464496 3
[2856] Target.TestMethod(): 19:03:40.2465936 6
[2976] Target.TestMethod(): 19:03:40.3467376 4
[2856] Target.TestMethod(): 19:03:40.4468816 7
[2976] Target.TestMethod(): 19:03:40.5470256 5
[2856] Target.TestMethod(): 19:03:40.6471696 8
[2976] Target.TestMethod(): 19:03:40.7473136 6
[2856] Target.TestMethod(): 19:03:40.8474576 9
Thread [2856] Done
[2976] Target.TestMethod(): 19:03:40.9476016 7
[2976] Target.TestMethod(): 19:03:41.1478896 8
[2976] Target.TestMethod(): 19:03:41.3481776 9
Thread [2976] Done

So you see clearly that two threadpool threads are activated.

Willy.


 
Reply With Quote
 
Coot
Guest
Posts: n/a
 
      1st May 2004
Willy,

The behavior seems to be related to how quickly the threads execute.

I modified your code, which uses a 2-second thread duration, to make 3
calls instead of two. All three were executed on a different thread.

However, I then changed it to a 0.2-second thread duration. This time
all 3 calls executed in sequence on the same thread.

And finally, I hunted for the sweet spot and found that with a 0.5
thread duration, the first and second calls executed on different
threads, but the 3rd executed on the same thread as the first.

Not sure why there is some delay in scheduling onto a new thread, but
it seems that the first request is executed immediately, the second is
executed after waiting a 2 or 3 tenths of a second, and the 3rd is
executed after waiting 5 tenthds of a second. Since all were
dispatched within microseconds of each other, I don't understand why
the delay in initiating their execution.

Perhaps this is a tunable policy of the thread pool manager???

--
Dave Hein



"Willy Denoyette [MVP]" <(E-Mail Removed)> wrote in message news:<(E-Mail Removed)>...
[snip]
> Well, this code:
>
> using System;
> using System.Threading;
> namespace Willys
> {
> class Tester
> {
> static void Main()
> {
> Target t = new Target();
> t.SpawnEm();
> }
> }
> }
>
> public class Target {
> public delegate int LaunchProc(TimeSpan ts, out int v);
> public int TestMethod( TimeSpan callDuration, out int threadId )
> {
> threadId = AppDomain.GetCurrentThreadId();
> int myThreadId = threadId;
> int count = 10;
> TimeSpan subDuration = TimeSpan.FromTicks( callDuration.Ticks /count );
> Type t = this.GetType();
> for (int i = 0; i < count; ++i)
> {
> Thread.Sleep( subDuration );
> Console.WriteLine("[" + myThreadId.ToString() + "] "
> + t.FullName + ".TestMethod(): " + DateTime.Now.TimeOfDay + " "
> + i.ToString() );
> }
> return threadId;
> }
> public void SpawnEm() {
> int count = 2;
> IAsyncResult[] asr = new IAsyncResult[count];
> int threadId = 0;
> LaunchProc pfn = new LaunchProc(this.TestMethod);
> for (int t = 0; t< count; t++) {
> asr[t] = pfn.BeginInvoke(new TimeSpan(20000000),out threadId, null,
> null);
> }
> foreach(IAsyncResult ar in asr)
> {
> pfn.EndInvoke(out threadId, ar);
> Console.WriteLine("Thread [{0}] Done", threadId);
> }
> }
> }
>
> Gives this:

[snip]
> Thread [2856] Done

[snip]
> Thread [2976] Done
>
> So you see clearly that two threadpool threads are activated.
>
> Willy.

 
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
HELP - Why are Worker thread's child thread's entering WaitSleepJoin? Plus Context Deadlock.... celoftis Microsoft Dot NET Framework 8 2nd Oct 2007 08:17 PM
HELP - Why are Worker thread's child thread's entering WaitSleepJoin? Plus Context Deadlock.... hzgt9b Microsoft VB .NET 0 29th Sep 2007 09:19 PM
HELP - Why are Worker thread's child thread's entering WaitSleepJoin? Plus Context Deadlock.... hzgt9b Microsoft VB .NET 0 28th Sep 2007 07:21 PM
Thread.Interrupt and asynchronous delegates Jeroen Mostert Microsoft Dot NET Framework 0 14th Jul 2006 02:55 PM
Asynchronous Invoke and the UI thread (using delegates) =?Utf-8?B?YnJpc2Vycw==?= Microsoft VB .NET 7 6th Mar 2006 06:45 PM


Features
 

Advertising
 

Newsgroups
 


All times are GMT +1. The time now is 07:38 PM.