Q:

Why is my async callback running in the same thread?

I'm trying to use the FtpWebRequest async calls (BeginGetResponse / EndGetResponse).
However, it appears that the callback from BeginGetResponse is running in the same thread as my application, when I was under the impression it would use a different (and thread pool) thread. This means my application blocks inside the callback before continuing.
I've setup a LINQPad proof-of-concept as follows:
"Starting".Dump();
Thread.CurrentThread.GetHashCode().Dump(); 
Thread.CurrentThread.IsThreadPoolThread.Dump();

IAsyncResult result = request.BeginGetResponse((ar) => 
{
     "Inside Callback".Dump();
     Thread.CurrentThread.GetHashCode().Dump();
     Thread.CurrentThread.IsThreadPoolThread.Dump();
     var resp = request.EndGetResponse(ar);
     "Callback Complete".Dump();
}, null);

"After Callback".Dump();

This prints output as follows:
Starting
33
False
Inside Callback
33
False
Callback Complete
After Callback

What I would expect is something like this (assuming the callback took long enough to run):
Starting
33
False
Inside Callback
44
True
After Callback // App continues despite callback running
Callback Complete

With the callback running on the same application thread it means if something inside the callback takes a long time (e.g. introducing a Thread.Sleep for argument's sake), my application blocks there. This means I cannot setup a timeout on the request (e.g. with a ThreadPool.RegisterWaitForSingleObject).
Am I missing something here?

A:

When an asynchronous operation can be completed immediately by the BeginXXX method, it doesn't run the callback on a thread-pool thread but sets the IAsyncResult.CompletedSynchronously Property to true and executes the callback synchronously.

