9

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

没有记录错误或抛出异常,但浏览器永远显示“Waiting for 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();
    }
}

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

<add key="aspnet:UseTaskFriendlySynchronizationContext" value="true"/>

神奇的词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;
            });
    }
}

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

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

以下内容适用于剃刀视图引擎,但不适用于 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();
    }
}

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

4

2 回答 2

11

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

James Manning 的建议是正确的,但您必须得到await的结果ConfigureAwait,如下所示:

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

一般来说,混合同步和异步代码是一个非常糟糕的主意,除非你真的知道你在做什么。使控制器动作异步会好得多。

于 2012-07-06T20:10:53.880 回答
1

我已经在 beta 中进行了异步工作。我没有测试过,但我猜这是因为你的控制器方法不是异步的。将其更改为:

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

    // it never gets here 
    return View();
}
于 2012-07-06T15:41:47.190 回答