public class HomeController : Controller
{
public ActionResult Index()
{
Task<string> t = DownloadStringTaskAsync(new Uri("http://www.google.com/search?q=aspnet"));
t.Wait();
string res = t.Result;
return View((object)res);
}
Task<string> DownloadStringTaskAsync(Uri address)
{
TaskCompletionSource<string> tcs = new TaskCompletionSource<string>();
WebClient wc = new WebClient();
wc.DownloadStringCompleted += (s, e) => tcs.SetResult(e.Result);
wc.DownloadStringAsync(address);
return tcs.Task;
}
}
The action will never return and the request will simply timeout.
We are using TPL tasks for all asynchronous operations and had to wrap some of WebClient's methods until we switch to framework 4.5.
The above method DownloadStringTaskAsync
is a simplified version of one of those wrappers.
What I can't figure out is why waiting on the task deadlocks the thread in aspnet and works fine in console or desktop applications.
Here's how the deadlocked threads look like.
request thread
[In a sleep, wait, or join]
mscorlib.dll!System.Threading.Monitor.Wait(object obj, int millisecondsTimeout, bool exitContext) + 0x18 bytes mscorlib.dll!System.Threading.ManualResetEventSlim.Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) + 0x264 bytes
mscorlib.dll!System.Threading.Tasks.Task.InternalWait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) + 0x166 bytes mscorlib.dll!System.Threading.Tasks.Task.Wait(int millisecondsTimeout, System.Threading.CancellationToken cancellationToken) + 0x41 bytes
mscorlib.dll!System.Threading.Tasks.Task.Wait() + 0xb bytes
TCSProblem.DLL!TCSProblem.Controllers.HomeController.Index() Line 16 + 0xa bytesWebClient thread
[In a sleep, wait, or join]
mscorlib.dll!System.Threading.Monitor.Enter(object obj, ref bool lockTaken) + 0x14 bytes
System.Web.dll!System.Web.AspNetSynchronizationContext.CallCallback(System.Threading.SendOrPostCallback callback, object state) + 0x53 bytes
System.Web.dll!System.Web.AspNetSynchronizationContext.Post(System.Threading.SendOrPostCallback callback, object state) + 0x9 bytes
System.dll!System.ComponentModel.AsyncOperation.Post(System.Threading.SendOrPostCallback d, object arg) + 0x29 bytes
System.dll!System.Net.WebClient.PostProgressChanged(System.ComponentModel.AsyncOperation asyncOp, System.Net.WebClient.ProgressData progress) + 0x25c bytes