仅返回视图异步的控制器操作是否必要?

时间:2018-09-27 13:36:03

标签: c# .net asp.net-mvc asynchronous async-await

执行以下基本操作:

[HttpGet]
public IActionResult Index()
{
    return View();
}

修改它以使用异步/等待:

[HttpGet]
public async Task<IActionResult> Index()
{
    return await Task.Run(() => View());
}

我很困惑这是否会改善我的代码。据我了解,await关键字将释放调用线程,以便可以在其他地方使用它,从而更好地利用可用线程。

但是我实际上没有做任何其他事情,除了这一件事正在返回视图。使用async关键字实际上会在编译后的代码中引入状态机,从而增加了复杂性。

使该动作异步值得吗?有没有更好的方法来修改它以使其异步?

2 个答案:

答案 0 :(得分:5)

简短的回答是“否”。由于async中没有View()发生任何事情,因此执行中没有地方可以让编译器释放线程以允许其他工作在同一地方进行线程。

我想说,使此特定方法异步可能会(甚至略微)提高性能,因为一旦使用async关键字,编译器将需要修改您的代码,使执行的过程更复杂。 / p>

如果您实际上还有许多其他活动都在利用async的优势,那么使我看到async的唯一好处就是保持一致性。如果您真的希望具有Task<T>签名以保持一致性,则可以考虑:

public Task<IActionResult> Index()
{
    return Task.FromResult(View());
}

(请注意,没有涉及async个关键字,也没有Task.Run涉及到要运行的新任务)

答案 1 :(得分:2)

在我看来,您应该重新阅读Microsoft的TAP文档,并更好地了解如何使Task为您工作。

在您的示例中:

public Task<IActionResult> Index()
{
    return Task.FromResult(View());
}

从本质上来说,这只是返回一些HTML,Javascript和CSS,因此它毫无意义,这意味着,当您将Task添加到普通函数中时,开销会变得很昂贵。

现在,如果您有这样的事情:

public Task<IActionResult> Index()
{
    var users  = DbContext.GetUsersAsync();
    var groups = DbContext.GetGroupsAsync();

     await Task.WhenAll(users,groups);

    var m = new Model(){
     Users = users.Result,
     Groups = groups.Result
    }

    return View(m);
}

在这种情况下,Task是有意义的,您实际上是在同时执行两个不同的I / O功能,然后等待所有这些功能完成后再继续。您正在花费要分别处理每个调用所花费的时间,并希望将其减少一半(以阻止潜在的CPU线程为另一个“网络”用户访问同一文档的代价)。

 public Task<IActionResult> Index()
    {
        var users  = await DbContext.GetUsersAsync();
        var groups = await DbContext.GetGroupsAsync();

        var m = new Model(){
         Users = users,
         Groups = groups
        }

        return View(m);
    }

在我的第三个示例中,即使它使用Async / Await,它仍然可以一一运行所有内容,因此浪费了宝贵的线程。

我唯一推荐的一件事是Task无法在庞大的用户群中很好地扩展,因此在开发Web解决方案时,请记住用户的未来潜在增长,并倾向于使用Task-基础的功能。

https://docs.microsoft.com/en-us/dotnet/standard/asynchronous-programming-patterns/task-based-asynchronous-pattern-tap