C# 异步方法加await调用不就变成同步方法了吗

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了C# 异步方法加await调用不就变成同步方法了吗相关的知识,希望对你有一定的参考价值。

请问这样理解错了吗,如果理解错了,请指正。如果没理解错,那么这样调用异步方法和调用普通方法有什么区别

不一样

同步方法在调用的时候他们是同一个线程的, 而异步调用的时候会起新的线程
比如:
A在线程1中运行, 调用同步方法B, 则线程1运行方法B, 然后返回A中调用的位置
如果A调用了异步方法C(加await), 则创建线程2来运行方法C, 同时线程1进入等待状态. 当C 执行完成后, 通知线程1, 然后线程2结束, 线程1继续向下执行
参考技术A

如果你是在某些代码里看到了await的用法,奇怪为啥不用普通的同步调用,那么有两个解释:

    C#的异步写法async是要求整个调用链都是这种写法,比如说A方法要调用异步的B,那A方法也得是标记为async,一直到最终得调用者,比如说是Form得按钮,一般不是异步得,所以就用了await

    某些库写成异步的,但调用者不熟悉异步写法或者不知道其好处,就简单写成await让编译通过。

C# 使用多个异步方法

在一个异步方法中,可以调用一个或多个异步方法。如何编写代码,取决于一个异步方法的结果是否依靠于另一个异步方法。

01 按顺序调用异步方法

使用 await 关键字可以调用每个异步方法。在有些情况下,如果一个异步方法依赖另一个异步方法的结果,await 关键字就非常有用。在这里,GreetingAsync 异步方法的第二次调用完全独立于其第一次调用的结果。这样,如果每个异步方法都不使用 await,那么整个 MultipleAsyncMethods 异步方法将更快地返回结果,如下所示:

private async static void MultipleAsyncMethods()

  string sl = await GreetingAsync("Stephanie"); 
  string s2 = await GreetingAsync("Matthias");
  Console.WriteLine($"Finished both methods.Environment.NewLine) " +
    $"Result 1: s1Environment.NewLine Result 2:s2");

02 使用组合器

如果异步方法不依赖于其他异步方法,则每个异步方法都不使用 await,而是把每个异步方法的返回结果赋值给 Task 变量,就会运行得更快。GreetingAsync 方法返回 Task<string>。这些方法现在可以并行运行了。组合器可以帮助实现这一点。一个组合器可以接受多个同一类型的参数,并返回同一类型的值。多个同一类型的参数被组合成一个参数来传递。Task 组合器接受多个 Task 对象作为参数,并返回一个 Task。

示例代码调用 Task.WhenAll 组合器方法,它可以等待,直到两个任务都完成:

private async static void MultipleAsyncMethodsWithCombinators1()

  Task<string> tl = GreetingAsync("Stephanie");
  Task<string> t2 = GreetingAsync("Matthias"); 
  await Task.WhenAll(t1, t2);
  Console.WriteLine($"Finished both methods.Environment.NewLine) " +
    $"Result 1:t1.ResultEnvironment.NewLine Result 2: t2.Result");

Task 类定义了 WhenAll 和 WhenAny 组合器。从 WhenAll 方法返回的 Task,是在所有传入方法的任务都完成了才会返回 Task。从 WhenAny 方法返回的 Task,是在其中一个传入方法的任务完成了就会返回 Task。

Task 类型的 WhenAll 方法定义了几个重载版本。如果所有的任务返回相同的类型,那么该类型的数组可用于 await 返回的结果。GreetingAsync 方法返回一个 Task<string>,等待返回的结果是一个字符串(string)形式。因此,Task.WhenAll 可用于返回一个字符串数组:

private async static void MultipleAsyncMethodsWithCombinators2()

  Task<string> t1 = GreetingAsync("Stephanie"); 
  Task<string> t2 = GreetingAsync("Matthias"); 
  string[] result = await Task.WhenAll(t1, t2);
  Console.WriteLine($"Finished both methods.Environment.NewLine " +
  $"Result 1:result[0]Enviornment.NewLine Result 2:result[1]");

只有等待的所有任务都完成时某个任务才能继续,WhenAll 方法就有实际用途。当调用任务在等待完成的任何任务都完成才能执行操作时,可以使用 WhenAny 方法。它可以使用任务的结果继续。

以上是关于C# 异步方法加await调用不就变成同步方法了吗的主要内容,如果未能解决你的问题,请参考以下文章

C# 异步编程

async await 同步方法调用异步方法死锁

“异步”调用图中的最后一次调用是不是需要同步?

[C#] 走进异步编程的世界 - 剖析异步方法(下)

async和await

async和await