【问题标题】:C# async and await keywords not working as expected with property getter [duplicate]C# async 和 await 关键字无法按预期使用属性 getter [重复]
【发布时间】:2023-04-09 02:30:01
【问题描述】:

你能简单解释一下为什么这段代码的前两行没有并行运行吗?我怎样才能让它并行工作?

SensorLeft 和 SensorRight 属于同一类,Distance 是它的公共属性,调用它的 get 方法时需要一些时间来计算。

我做错了什么?我应该将距离计算作为异步函数而不是正确的吗?

public async void GetDistance()
{
    await Task.Run(() => LeftDistance = SensorLeft.Distance);
    await Task.Run(() => RightDistance = SensorRight.Distance);
    Distance = RightDistance < LeftDistance ? RightDistance:LeftDistance;
}

【问题讨论】:

  • 当您 await 第一个任务时,您正在等待它完成,然后再移动到下一行代码。先分配任务,然后使用Task.WhenAll让它们同时运行。
  • async void 仅用于事件处理程序。您应该使用async Taskawait 表示 await 等待异步操作完成。开始并行工作的是Task.Run,而不是await。如果您希望操作并行运行,则将返回的任务存储在一个数组中,并使用await Task.WhenAll(tasks) 等待它们完成。
  • 此外,除非您调用执行 IO 完成端口的异步方法,否则这不仅速度较慢,而且使用线程可能会导致更多性能问题。
  • 请记住,await 不会使某些东西异步。 Await 检查任务是否完成,如果未完成,则返回,以便调用者可以找到更多工作要做。 在这种情况下,方法的其余部分将完成等待的任务。如果您认为 await 使某些事情变得异步,请立即从您的脑海中清除这种不正确的信念。

标签: c# .net properties async-await getter


【解决方案1】:

当编译器遇到await 关键字时,它会自动在任务调度器中调度一个任务。该操作等待(以非阻塞方式)任务完成,然后继续执行其余的代码块。

要让您的代码并行运行,您需要将其修改为

public async Task GetDistance()
{
    var leftDTask = Task.Run(() => LeftDistance = SensorLeft.Distance);
    var rightDTask= Task.Run(() => RightDistance = SensorRight.Distance);
    await Task.WhenAll(leftDTask,rightDTask);
    Distance = RightDistance < LeftDistance ? RightDistance:LeftDistance;
}

Task.WhenAll 有一个重载返回 Task&lt;TResult[]&gt; Task.WhenAll&lt;TResult[]&gt;。你可以把你的代码替换成

public async Task GetDistance()
{
    var leftDTask = Task.Run(() => SensorLeft.Distance);
    var rightDTask= Task.Run(() => SensorRight.Distance);
    var results= await Task.WhenAll(leftDTask,rightDTask);
    Distance = Math.Min(results[0],results[1]);
}

但是,这不是一个好的解决方案。如果您希望获取距离真正异步,您应该创建一个异步获取方法,而不是将其包装到 Task.Run 中。

【讨论】:

  • 谢谢!将其包装到 Task.Run 或使 get 异步有什么区别?顺便说一句,我可以将属性 getter 设为异步还是必须将其设为函数?
  • 属性getter不支持异步,必须做一个getter函数。我承认将同步操作包装到 Task.Run 是进行异步操作的最快方法,但不建议这样做。 Stephen Toub MSFT 在此博客中有更好的解释 blogs.msdn.microsoft.com/pfxteam/2012/03/24/…
猜你喜欢
  • 1970-01-01
  • 2019-12-04
  • 2015-05-04
  • 2012-11-28
  • 2020-03-11
  • 1970-01-01
  • 1970-01-01
  • 2019-09-25
  • 1970-01-01
相关资源
最近更新 更多