【问题标题】:C# - How to create an inline async Task [duplicate]C# - 如何创建内联异步任务 [重复]
【发布时间】:2021-12-16 09:15:22
【问题描述】:

正如问题所说,我想知道如何创建内联异步任务。我尝试了以下方法(当然,T 这是一个通用抽象,你应该用你想要的任何对象替换它):

var task = new Task<T>(() => new T());
var taskResult = await task;

但是,当 taskResult 行被执行时,程序就会冻结 - 很可能是因为 Task 不是异步的。我知道我可以创建一个异步方法并对其执行等待,但由于我正在开发单元测试,我更喜欢内联任务定义。

那么,我的问题是:我将如何编写一个不会冻结程序的可等待内联任务?

编辑:背景是我正在使用 Moq 并且需要模拟一些 async Task(...) 方法。为了模拟这些,.Setup(...).Returns(...) 要求我返回一个任务。

我尝试使用上面的代码进行内联创建,以及单元测试方法之外的async Task&lt;T&gt; 方法。内联创建只是冻结了,而该方法运行得非常好。我得出的结论是,这两者之间唯一真正的区别是方法是异步的,而内联代码不是;因此为什么我认为失败“很可能是因为内联任务不是异步的”。

我试图四处寻找这个问题的答案,但除了new Task&lt;T&gt;(() =&gt; ...) 之外什么都没有看到。因此,我问了这个问题,以帮助将来可能遇到此问题的其他人。很抱歉一开始就让我的意图和问题不清楚。我希望这能澄清它!

【问题讨论】:

  • 你也可以这样使用:var taskResult = await Task.Run(() =&gt; new T());.
  • 你到底想在这里做什么?构造函数确实没有任何异步要做(构造函数本质上是同步的),所以:你为什么希望它是异步的?我很欣赏您可能正在简化,但是:细节真的很重要。老实说,显示的代码的正确版本是:var result = new T(); - 但是,Task.FromResult(new T()) 可能有用,注意异步和线程不是一回事。您是否尝试在另一个线程上运行构造函数?如果是这样:为什么?
  • 然后:Task.FromResult(new T())
  • FWIW:我认为这里的负面回应是因为您提出了一个意图真的很不清楚的问题,然后立即发布了一个真的,对于那个不清楚的问题,真是奇怪的答案;如果你真的明确了你想要做什么,人们就会说“task.fromresult”,并且:我们都会继续我们的一天
  • 这是XY Problem的情况。

标签: c# task


【解决方案1】:

事实证明,我需要做的就是用内联异步函数包装任务。这会在调用 task() 时创建一个等待任务。我解决的方法是:

var task = new Func<Task<T>>(async () => new T());
var taskResult = await task();

编辑:正如其他人指出的那样,在这种情况下您应该使用Task.FromResult(new T())

【讨论】:

  • 为什么要将对象构造包装在异步函数中?
  • 正如我所说,我正在做单元测试。我在帖子中没有提到这一点,但我在嘲笑(通过 Moq)async Task 方法和 `.Setup(...).Returns(...) 方法因此有时需要我返回一个对象。当然,我可以将对象构造移到其他地方,但这不是重点。
  • 那你为什么不直接使用Task.FromResult(new T())
  • 老实说,我不知道这种方法。谢谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2016-03-29
  • 2018-07-05
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 2015-07-04
  • 1970-01-01
相关资源
最近更新 更多