【问题标题】:Is there any difference between normal lambda and async lambda below?下面的普通 lambda 和异步 lambda 有什么区别吗?
【发布时间】:2018-05-04 01:37:09
【问题描述】:

假设我有一个如下库,用于非基于 UI 的应用程序 (ASP.NET) 和基于 UI 的应用程序(WinForm 和 WPF)。不幸的是,我无法避免混合 IO 密集型工作和 CPU 密集型工作,但我让消费者​​通过 Task.Run 调用 DummyWorkAsync 或不基于他们的应用程序类型(非 UI 或基于 UI 的应用程序)。

class DummyService
{
  public static async Task<int> DummyWorkAsync()
  {
    // Do some I/O first.
    await Task.Delay(1000);

    // Tons of work to do in here!
    for (int i = 0; i != 10000000; ++i)
      ;

    // Possibly some more I/O here.
    await Task.Delay(1000);

    // More work.
    for (int i = 0; i != 10000000; ++i)
      ;

    return 0;
  }
}

这允许基于 UI 的消费者正确地使用Task.Run 来调用服务,而 ASP.NET 客户端将直接调用该方法,如下所示。

private async void MyButton_Click(object sender, EventArgs e)
{
  await Task.Run(() => DummyService.DummyWorkAsync());
}

public class Home: Controller
{
  public async Task<ActionResult> IndexAsync()
  {
    var result = await DummyService.DummyWorkAsync();
    return View(result);
  }
}

问题

我对基于 UI 的应用程序很感兴趣。如果我使用有什么区别

private async void MyButton_Click(object sender, EventArgs e)
{
  await Task.Run(async () => await DummyService.DummyWorkAsync());
}

而不是

private async void MyButton_Click(object sender, EventArgs e)
{
  await Task.Run(() => DummyService.DummyWorkAsync());
}

?

【问题讨论】:

  • 第一个只有在 DummyWorkAsync 在 UI 线程上完成后需要做某事时才有用,所以从技术上讲,它实际上是在等待它完成但同时不阻塞 UI 线程.
  • @Clemens:因为“混合”DummyWorkAsync 中有一些 CPU 绑定的作品。对于这种混合异步方法,我们需要在基于 UI 的应用程序中使用 Task.Run
  • 既然您的 IO 先行(我的意思是先等待 Task.Delay),为什么不直接添加 ConfigureAwait(false) 呢?然后你也可以从 UI 调用它,而不用包裹在 Task.Run 中。

标签: c# asp.net wpf lambda async-await


【解决方案1】:

不,没有(显着)差异。你基本上是在问有什么区别

static Task<int> Something() {
    return SomethingAsync();
}

static async Task<int> Something() {
    return await SomethingAsync();
}

除了在您的情况下,还有一个包装任务 (Task.Run),因此在这种情况下,您可能会在同一问题的其他问题中发现异常传播的差异。

正因为如此 - 只需使用

await Task.Run(() => DummyService.DummyWorkAsync());

也就是说,这样做的原因还不是很清楚。由于您的 IO 优先 - 您可以使用 ConfigureAwait(false) 来防止将控制权返回到当前同步上下文(无论如何这对于库来说都是一个好习惯)。在这种情况下,在您第一次等待之后,其余的(繁重的 CPU 工作)将在线程池线程(至少使用默认调度程序)上执行,因此您首先不需要使用 Task.Run

public static async Task<int> DummyWorkAsync()
{
    // Do some I/O first.
    await Task.Delay(1000).ConfigureAwait(false);

    // Tons of work to do in here!
    // no problem, we are not on UI thread anyway
    for (int i = 0; i != 10000000; ++i)
        ;

    // Possibly some more I/O here.
    await Task.Delay(1000).ConfigureAwait(false);

    // More work.
    for (int i = 0; i != 10000000; ++i)
       ;

    return 0;
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-01-15
    • 1970-01-01
    • 1970-01-01
    • 2010-10-20
    • 1970-01-01
    • 1970-01-01
    • 2020-11-12
    • 1970-01-01
    相关资源
    最近更新 更多