Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/338.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 仅返回视图的控制器操作是否需要异步?_C#_.net_Asp.net Mvc_Asynchronous_Async Await - Fatal编程技术网

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

C# 仅返回视图的控制器操作是否需要异步?,c#,.net,asp.net-mvc,asynchronous,async-await,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()); } [HttpGet] 公共异步任务索引() { 返回等待任务。运行(()=>View()); } 我不知道这是否会改

采取这一基本行动:

[HttpGet]
public IActionResult Index()
{
    return View();
}
修改它以使用异步/等待:

[HttpGet]
public async Task<IActionResult> Index()
{
    return await Task.Run(() => View());
}
[HttpGet]
公共异步任务索引()
{
返回等待任务。运行(()=>View());
}
我不知道这是否会改进我的代码。据我所知,wait关键字将释放调用线程,以便它可以在其他地方使用,从而更好地利用可用线程

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


让这个动作异步化值得吗?有没有更好的方法修改它以使其异步

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

我想说的是,使这个特定的方法异步可能会(甚至稍微)降低性能,因为一旦使用
async
关键字,编译器将需要修改代码,使执行的内容更加复杂

我所看到的使其
async
的唯一好处是,如果您有许多其他操作实际上利用了
async
,那么它将具有一致性。如果出于一致性的目的,您确实希望有一个
任务
签名,您可以考虑:

public Task<IActionResult> Index()
{
    return Task.FromResult(View());
}
公共任务索引()
{
返回Task.FromResult(View());
}

(请注意,不涉及任何
async
关键字,也不涉及任何
Task。请运行一个新任务)

我觉得您应该重新访问Microsoft的TAP文档,更好地了解如何让任务为您工作

在您的示例中:

public Task<IActionResult> Index()
{
    return Task.FromResult(View());
}
公共任务索引()
{
返回Task.FromResult(View());
}
它本质上只是返回一些HTML、Javascript和CSS,所以它不是毫无意义的,这意味着,当您将任务添加到一个普通函数中时,会有开销,这可能会变得非常昂贵

现在如果你有这样的东西:

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);
}
公共任务索引()
{
var users=DbContext.GetUsersAsync();
var groups=DbContext.GetGroupsAsync();
等待任务。WhenAll(用户、组);
var m=新模型(){
Users=Users.Result,
组=组。结果
}
返回视图(m);
}
在这个场景中,任务是有意义的,您实际上是同时执行两个不同的I/O函数,然后等待它们全部完成,然后再继续。您将占用单独处理每个调用所需的时间,并有望将其减少一半(代价是阻止另一个“web”用户访问同一文档的潜在CPU线程)

公共任务索引()
{
var users=await DbContext.GetUsersAsync();
var groups=await DbContext.GetGroupsAsync();
var m=新模型(){
用户=用户,
组=组
}
返回视图(m);
}
在我的第三个示例中,尽管它使用Async/Await,但它仍然一个接一个地运行所有内容,因此浪费了宝贵的线程

我唯一可以推荐的是,Task不能很好地扩展到大量用户,因此在开发web解决方案时,请记住用户未来的潜在增长,并依靠基于Task的功能


您还没有真正将控制器修改为异步。所有请求都由单独的线程处理
async/await
旨在避免在执行IO工作时阻塞这些线程。如果您使用
wait Task.Run()
您只需使用一个新的任务/线程即可完成原始线程可以轻松完成的工作
wait Task.Run()
几乎总是错误的。-
Task.Run()
-“TPL,请在我忙于做其他事情时找到一个线程来运行此代码”
wait
-“我在这个线程上没有什么有用的工作要做-去看看是否有其他东西可以利用它”@Damien\u不信者这只有在ASP上下文中才是真的。这是理所当然的,但您的语句暗示它适用于其他非常不正确的上下文。@Servy-在asp上下文中是正确的。这在控制台上下文中是正确的。如果它正在运行其他代码,而这些代码会频繁地等待自身,而不会占用CPU,则在具有“受祝福线程”(例如UI线程)的上下文中,这可能是正确的。如果您试图将CPU限制的工作推离UI线程,则这是不正确的。但我不经常看到它在那种情况下被使用。这是一个人为的问题。当您需要数据来填充模型时,模型会发生变化。当某个元素正在执行异步I/O时,使某个操作异步是有利可图的。我只是想问一下,为什么任务不能很好地扩展到大型用户群?还有,什么是大用户群?TAP是一个很好的范例,可以让一些功能实现得非常快,但是人们习惯于滥用它并包装与任务相关的所有I/O,就像一些开发人员用try-catch包装每四行代码一样,没有意识到这一切都是有代价的。此外,当一个函数有一个任务正在执行,并且它正在消耗几个线程时,如果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);
    }