简体   繁体   English

下面的普通Lambda和异步Lambda之间有什么区别吗?

[英]Is there any difference between normal lambda and async lambda below?

Assume I have a library as follows for both non-UI based apps (ASP.NET) and UI based apps (WinForm and WPF). 假设我有一个针对非基于UI的应用程序(ASP.NET)和基于UI的应用程序(WinForm和WPF)的库,如下所示。 Unfortunately I cannot avoid mixing IO-bound work and CPU-bound work but I let the consumers invoke DummyWorkAsync via Task.Run or not based on their application types (non-UI or UI based apps). 不幸的是,我无法避免将IO绑定的工作和CPU绑定的工作混在一起,但是我让使用者通过Task.Run调用DummyWorkAsync ,或者不基于他们的应用程序类型(非UI或基于UI的应用程序)来调用DummyWorkAsync

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;
  }
}

This allows UI-based consumer to properly use Task.Run to call the service, while ASP.NET clients would just call the method directly as follows. 这使基于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);
  }
}

Question

I am interested in the UI-based apps. 我对基于UI的应用感兴趣。 Is there any difference if I use 如果我使用有什么区别

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

rather than 而不是

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

?

No, there is no (significant) difference. 不,没有(重大)差异。 You are basically asking what's the difference between 您基本上是在问两者之间有什么区别

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

and

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

Except in your case there is one more wrapping task ( Task.Run ), so differences in exceptions propagation for example which you may find in another questions on the same issue are not relevant in this case. 除了您的情况之外,还有另一个包装任务( Task.Run ),因此在同一情况下,您可能会在同一问题的另一个问题中发现异常传播的差异(例如,您可能会发现它们之间的差异)。

Because of that - just use 因此-只需使用

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

That said, reasons for doing that are not that clear. 也就是说,这样做的原因尚不清楚。 Since your IO goes first - you can use ConfigureAwait(false) to prevent returning control to current synchronization context (which is good practice for libraries anyway). 由于您的IO排在第一位-您可以使用ConfigureAwait(false)来防止将控制权返回到当前的同步上下文(无论如何,这对于库是一个好习惯)。 In that case, after your first await the rest (heavy CPU work) will be executed on thread pool thread (with default scheduler at least), so you won't need to use Task.Run in the first place: 在这种情况下,第一次等待之后(其余的大量工作)将在线程池线程上执行(至少使用默认调度程序),因此您无需首先使用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;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM