Consider the following (based on the default MVC template), which is a simplified version of some βstuffβ that happens in the background - it is perfectly completed and shows the expected result, 20:
public ActionResult Index() { var task = SlowDouble(10); string result; if (task.Wait(2000)) { result = task.Result.ToString(); } else { result = "timeout"; } ViewBag.Message = result; return View(); } internal static Task<long> SlowDouble(long val) { TaskCompletionSource<long> result = new TaskCompletionSource<long>(); ThreadPool.QueueUserWorkItem(delegate { Thread.Sleep(50); result.SetResult(val * 2); }); return result.Task; }
However, now if we add async to the mix:
public static async Task<long> IndirectSlowDouble(long val) { long result = await SlowDouble(val); return result; }
and change the first line of the route to:
var task = IndirectSlowDouble(10);
then does not work ; occasionally. If we add breakpoints, return result; in the async method only happens after the route is already completed - basically, it seems that the system does not want to use any thread to resume async until the request is complete. Even worse: if we used .Wait() (or gained access to .Result ), then it would be completely inhibited.
So: what's up with that? The obvious workaround is to "not include async " but this is not easy when using libraries, etc. Ultimately, there is no functional difference between SlowDouble and IndirectSlowDouble (although there is an obvious structural difference).
Note: the exact same thing in the console / winform / etc will work fine.
Marc Gravell Nov 29 '12 at 8:29 2012-11-29 08:29
source share