Рассмотрим следующее (на основе шаблона MVC по умолчанию), который представляет собой упрощенную версию некоторого "материала", который происходит в фоновом режиме - он отлично завершен и показывает ожидаемый результат, 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;
}
Однако теперь, если мы добавим в микс async:
public static async Task<long> IndirectSlowDouble(long val)
{
    long result = await SlowDouble(val);
    return result;
}
и измените первую строку маршрута на:
var task = IndirectSlowDouble(10);
 тогда  не работает; время от времени. Если мы добавим точки останова, return result; в методе async произойдет только  после, маршрут уже завершен - в основном, похоже, что система не хочет использовать какой-либо поток для возобновления async до тех пор, пока запрос не будет завершен. Хуже того: если бы мы использовали .Wait() (или получили доступ к .Result), тогда он будет полностью заторможен.
Итак: что с этим? Очевидным обходным решением является "не включать async", но это нелегко при использовании библиотек и т.д. В конечном счете нет функциональной разницы между SlowDouble и IndirectSlowDouble (хотя очевидная структурная разница).
Примечание: точно такая же вещь в консоли /winform/etc будет работать нормально.