【问题标题】:async and async composition in ASP.NET CoreASP.NET Core 中的异步和异步组合
【发布时间】:2017-11-21 12:55:12
【问题描述】:

我对如何使用异步和异步组合感到困惑,尤其是在 asp.net 核心中

这是案例 1:

这是控制器中的代码

    private readonly InfoService _infoService;
    public HomeController(InfoService infoService)
    {
        _infoService = infoService;
    }
    public IActionResult Index()
    {
        //Create a stopwatch for getting excution time  
        var watch = new Stopwatch();
        watch.Start();
        var country = _infoService.GetCountry();
        var state = _infoService.GetState();
        var city = _infoService.GetCity(state);
        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        ViewBag.Data = city;
        return View();
    }

    public async Task<IActionResult> About()
    {
        //Create a stopwatch for getting excution time  
        var watch = new Stopwatch();
        watch.Start();
        var country =  _infoService.GetCountryAsync();
        var state =  _infoService.GetStateAsync();
        var city =  _infoService.GetCityAsync();
        var content = await country;
        var count = await state;
        var name = await city;
        watch.Stop();
        ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
        ViewBag.Data = name;
        return View();
    }

这是信息服务中的代码

    public string GetCountry()
    {
        Thread.Sleep(3000); //Use - when you want to block the current thread.  
        return "VietNam";
    }
    public async Task<string> GetCountryAsync()
    {
        await Task.Delay(3000); //Use - when you want a logical delay without blocking the current thread.  
        return "VietNam";
    }
    public string GetState()
    {
        Thread.Sleep(5000); //Use - when you want to block the current thread.  
        return "the North";
    }
    public async Task<string> GetStateAsync()
    {
        await Task.Delay(5000); //Use - when you want a logical delay without blocking the current thread.  
        return "the North";
    }
    public string GetCity()
    {
        Thread.Sleep(6000); //Use - when you want to block the current thread.  
        return "HaNoi";
    }
    public async Task<string> GetCityAsync()
    {
        await Task.Delay(6000); //Use - when you want a logical delay without blocking the current thread.  
        return "HaNoi";
    }

运行 Index 动作,耗时 14003 毫秒

运行关于动作,耗时6016毫秒

在这种情况下,我认为它在 About 动作中并行运行 => 在异步中很好

情况2

我在关于操作中更改了少量代码

  var watch = new Stopwatch();
  watch.Start();
  var country = await _infoService.GetCountryAsync();
  var state = await _infoService.GetStateAsync();
  var city = await _infoService.GetCityAsync();
  watch.Stop();
  ViewBag.WatchMilliseconds = watch.ElapsedMilliseconds;
  return View();

本案结果:

运行 Index 动作,耗时 14003 毫秒

运行关于动作,大约需要> 14008 ms,它随时改变低或高,通常在中更高的时间索引动作

那么关于这个案子的行动会发生什么? 关于动作

两种情况的区别

当有多个请求/并发到关于两种情况下的操作时会发生什么和区别

[我知道与 Index 动作比较时它不是阻塞线程]

这是案例 3:

如果我想在 关于 操作中使用异步

  • get state from value of country 已返回
  • get city from value of country, state 已返回

我目前是这样用的:

  var country = await _infoService.GetCountryAsync();
  var state = await _infoService.GetStateAsync(country);
  var city = await _infoService.GetCityAsync(country,state);

那里有什么问题吗?在这种情况下,当有多个并发请求时会发生什么?

[我认为它在多并发请求中可能有价值,也可能没有价值]

在这种情况下使用异步的最佳方式是什么?

谢谢!

【问题讨论】:

  • 很明显,一个是串行运行,另一个是并行运行——问题是什么?
  • 感谢您的回复,导致我对 async 特别是 asp.net 核心中的 async 理解不佳,即无法理解异步如何在多并发请求环境中运行。我对@CodeFuller 的回答和 MickyD 的链接有了更深入的了解

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


【解决方案1】:

当你写作时

var country = await _infoService.GetCountryAsync();
var state = await _infoService.GetStateAsync();
var city = await _infoService.GetCityAsync();

你让你的任务被等待。在任务完成之前,控制流不会传递给下一个操作员。所以从这个意义上说,它与同步代码非常相似:

var country = _infoService.GetCountry();
var state = _infoService.GetState();
var city = _infoService.GetCity(state);

但是对于异步版本,如果某些 I/O 操作会阻塞进一步的执行,则该线程将被返回到线程池并可以被另一个操作使用。

关于案例3:

您可以使用Task.WhenAll() 让任务并行运行并等待所有任务完成:

var countryTask =  _infoService.GetCountryAsync();
var stateTask =  _infoService.GetStateAsync();
var cityTask =  _infoService.GetCityAsync();

await Task.WhenAll(new[] { countryTask, stateTask, cityTask });

任务完成后,您可以通过Task.Result 属性获得结果:

var country = countryTask.Result;

但是不要在未完成的任务上调用Task.ResultTask.Wait(),因为它会阻塞线程并贬低异步模型。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-10-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多