每当使用异步时,ASP.Net MVC 4控制器都会挂起

Ant*_*ony 9 c# asp.net-mvc task-parallel-library async-await

我正在使用带有.Net 4.5和ASP MVC 4 RC的Visual Studio 2012 RC.每当我使用异步时它就会挂起.控制器操作方法使用异步,但本身不是异步控制器方法.

没有记录错误或抛出异常,但浏览器永远显示"正在等待www.myweb.local ".

// Simplest possible async
public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 42);
    }
}

// simplest possible controller that uses the async
public class HomeController : Controller

    public ActionResult Index()
    {
        var waiter = new Waiter();
        var resultTask = waiter.GetValue();
        int result = resultTask.Result;

        // it never gets here 
        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

我已经完成了这个答案中提到的事情,但它仍然不起作用.即.web.config包含

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>
Run Code Online (Sandbox Code Playgroud)

魔术词await Task.Yield();是在异步方法中.

.Net框架版本是4.5.50501.我在IIS Express和IIS 6.0上观察到了这种行为.

我尝试将"2012年7月更新"应用于VS2012,但这并没有解决它.

这个答案表明,这可能是因为当我等待它时任务已经完成,但是如果是这样的话,这应该有效,但它不会:

public class Waiter
{
    public async Task<int> GetValue()
    {
        await Task.Yield();
        return await Task.Factory.StartNew(() => 
            {
                Thread.Sleep(1500);
                return 42;
            });
    }
}
Run Code Online (Sandbox Code Playgroud)

有几个人建议这ConfigureAwait(false)是必需的,但是这段代码也不起作用:

    public async Task<int> GetValue()
    {
        var task = new Task<int>(() => 42);
        return await task.ConfigureAwait(false);
    }
Run Code Online (Sandbox Code Playgroud)

以下适用于剃刀视图引擎,但不适用于spark.当然应该有办法让其他场景也能运作吗?可以在同步代码中不使用异步任务吗?

public class Waiter
{
    public async Task<int> GetValue()
    {
        return await Task.Factory.StartNew(() => 42);
    }
}

public class HomeController : Controller
{
    public async Task<ActionResult> IndexAsync()
    {
        await Task.Yield();
        var waiter = new Waiter();
        int result = await waiter.GetValue();

        return View();
    }
}
Run Code Online (Sandbox Code Playgroud)

我知道这不是发布的软件,但是微软的RC通常都很稳定,所以我很惊讶它失败了,并且以无益的方式失败了.

Ste*_*ary 11

就像这个问题一样,你正在造成僵局.

詹姆斯曼宁的建议是正确的,但你必须得到这样await的结果ConfigureAwait:

public async Task<int> GetValue()
{
    var task = new Task<int> (() => 42);
    return await task.ConfigureAwait(false);
}
Run Code Online (Sandbox Code Playgroud)

一般来说,混合同步和异步代码是一个非常糟糕的想法,除非你真的知道你在做什么.使控制器操作异步会更好.


Jam*_*rld 1

我在测试版中的异步工作得很好。我还没有测试过它,但我猜这是因为你的控制器方法不是异步的。改成这样:

public async Task<ActionResult> IndexAsync()
{
    var waiter = new Waiter();
    int result = await waiter.GetValue();

    // it never gets here 
    return View();
}
Run Code Online (Sandbox Code Playgroud)