【问题标题】:Why should I prefer using API async fucntions over wrapping synchronous ones with Task.Run?为什么我更喜欢使用 API 异步函数而不是使用 Task.Run 包装同步函数?
【发布时间】:2017-02-01 19:17:14
【问题描述】:

我知道这段代码有区别:

var streamWriter = new StreamWriter("something.txt");
streamWriter.WriteAsync("text");

还有这个:

var streamWriter = new StreamWriter("something.txt");
Task.Run(()=> streamWriter.Write("text"));

第一个更有意义。

在不同的情况下,当我等待结果时,这段代码:

var streamReader = new StreamReader("something.txt")
char[] chars = new char[10];

Task<int> task = streamReader.ReadAsync(chars, 0, chars.Length);
//Do something...

int num = await task;
//Do something with num...

比这更有意义:

var streamReader = new StreamReader("something.txt")
char[] chars = new char[10];

Task<int> task = Task.Run(()=>streamReader.Read(chars, 0, chars.Length));
//Do something...

int num = await task;
//Do something with num...

我猜想使用内置异步 API 不仅在清晰度上更好,而且它实际上比让 ThreadPool 线程无缘无故地等待更好、更有效地管理 ThreadPool 线程。

对吗?

【问题讨论】:

  • 这是典型的纯异步与异步超过同步的问题。
  • 赌注是实现DoSomethingSomethingAsync 方法的人理解问题域并且实际上在实现一个好的异步故事方面做得很好。另一种方式,产生一个显式任务来进行同步调用几乎是说“我不信任他们”。我认为你应该相信他们。
  • 一般来说,如果您有选择的话,使用异步方法应该总是比生成一个任务然后在该任务中调用同步方法更好。同样,假设创建异步方法的人知道他们在做什么。
  • 仅供参考,这个确切的主题在Lucian Wischik's "Six Essential Tips for Async" video series on Channel 9 的提示 4 中有详细介绍。

标签: c# asynchronous async-await task-parallel-library threadpool


【解决方案1】:

包装在Task.Run 中的同步调用将在该操作期间阻塞线程池线程。真正的异步实现will not

特别是对于流,确定操作是否“真正异步”可能有点棘手。例如,网络流始终是真正异步的,内存流永远不是真正异步的,文件流只有在向其构造函数传递特殊标志时才是真正异步的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-09-02
    • 2021-09-05
    • 1970-01-01
    • 2020-08-12
    • 2019-09-02
    相关资源
    最近更新 更多