使用async和await关键字的好处

Lam*_*fif 6 .net c# multithreading asynchronous task

我是C#中异步方法的新手.我已经读过这些关键字asyncawait通过异步某些方法帮助使程序更具响应性.我有这个片段:

第一道路

    public static void Main()
    {
        Console.WriteLine("Hello!! welcome to task application");
        Console.ReadKey();
        Task<string> ourtask = Task.Factory.StartNew<string>(() =>
        {
            return "Good Job";
        });
        ourtask.Wait();
        Console.WriteLine(ourtask.Result);
        Console.ReadKey();
    }
Run Code Online (Sandbox Code Playgroud)

第二种方式

 public static void Main()
        {
            Launch();
        }
        public static async void Launch()
        {
            Console.WriteLine("Hello!! welcome to task application");
            Console.ReadKey();
            Console.WriteLine(await GetMessage());
            Console.ReadKey();
        }

        public static Task<string> GetMessage()
        {
            return Task.Factory.StartNew<string>(() =>
                {
                    return "Good Job";
                });
        }
Run Code Online (Sandbox Code Playgroud)

我需要知道 :

  1. 这两种实现之间是否有区别(在并行性的概念中)?

  2. 如果我可以创建任务并等待它完成,那么使用asyncawait关键字有什么好处?

Jer*_*vel 57

假设您有一个边界检查点.每辆车都可以一个接一个地通过,让海关看看他们的车,看看他们是不是走私任何比利时巧克力.

现在假设你在你的大众甲壳虫中排成一行,在那里你几乎无法适应,在你成为一个24轮的monstertruck之前.你现在被困在这个庞然大物的很长一段时间,直到海关完成所有搜索之后才能转移给你,他们基本上只需要拍下来告诉你你很好.

为了对抗这种效率,我们在边境巡逻队的好朋友有了一个想法并安装了第二个检查站.现在他们可以传递两倍的人数而你可以只拿一个而不是等待monstertruck!

问题解决了吧?不完全是.他们忘了创建通往该检查站的第二条道路,因此所有交通仍然必须通过单车道,导致卡车仍然阻挡甲壳虫.

这与您的代码有什么关系?很简单:你也是这样做的.

当您创建新的时,Task您基本上创建了第二个检查点.但是,当您现在使用同步阻止它时.Wait(),您迫使每个人都走这条路.

在第二个示例中,您使用await它创建第二条道路并允许您的汽车与卡车同时处理.

  • @Servy为什么不发布一个更好的答案,而不是花费这么多精力批评这个? (18认同)
  • 这个例子并不能很好地代表这两种情况,也不能回答所提出的实际问题。这两种情况都不涉及任何并行性,这正是您在这里试图描述的。您的示例没有任何解释(即使以类比形式)什么是异步或为什么有人可能想要使用它(类比全部涵盖了完全同步操作)。这个答案根本没有任何技术价值。它没有做任何事情来解释实际发生的事情。显然有趣但没有任何意义的故事才是人们感兴趣的。 (4认同)
  • @ToddMenier 因为一个人可以写一整本书试图回答这个问题,但仍然无法涵盖所有​​内容。这个问题太宽泛了,无法成为一个可以回答的问题。这是这个答案的主要问题之一,除了充满技术不准确和错误信息之外,它甚至还没有接近“开始”来回答这个问题。写出一个实际的答案或多或少是不可能的。 (2认同)

Tod*_*ier 5

我将尝试直接回答问题:

  1. 您的两个示例都没有(有效地)涉及任何并行性。我看到它们之间有2个主要区别:1)第一个示例将在任务在第二个线程上运行时阻塞线程,这是毫无意义的; 2)第二个示例将提早退出。一旦await遇到问题,控制权立即返回Main(),并且由于您不等待返回的任务Launch()完成,因此程序将在此时退出。

  2. 使用asyncawaitvs.等待任务完成的好处是,await在任务运行时不会阻塞当前线程。在后台,await只要编译器遇到,它就将该方法的其余部分有效地重写为将在任务完成时调用的回调。这可以在任务运行时释放当前线程以执行其他操作,例如响应客户端应用程序中的用户输入或服务Web应用程序中的其他请求。

坦白说,这不是证明async/ 的好处的好例子await。您基本上是在说要执行CPU限制的工作,在完成该工作之前,您不希望执行任何其他操作。您也可以同步执行此操作。在进行I / O绑定工作时,例如在网络上进行调用(使用正确实现的异步库,例如HttpClient)进行调用时,异步确实发光,因为您不像第二个示例那样简单地将一个线程换为另一个线程。从字面上看,该I / O绑定工作不会占用任何线程

正如其他人所提到的,并行性完全是另一个主题。虽然async/ await可以是有助于您实现的有用结构,但其中涉及的内容更多。在我看来,在“继续”进行并行处理之前,最好更好地把握线程释放的好处。

就像其他人提到的那样,这是一个重要的话题,我强烈建议您查看其中的一些很棒的资源。由于我已经引用了Stephen Cleary的博客,因此我将继续进行完整介绍 -他的async / await简介和后续文章是该主题的出色入门。


Sae*_*Dah 5

我们有异步/等待编程的两个主要好处

1- 非阻塞编程

当您有不需要阻止执行的长时间运行的操作时。在这种情况下,您可以在等待长时间运行任务的结果的同时执行其他工作。

想象一下,我们有两个程序流,它们可以并行工作而不会相互阻塞。

示例: 假设我们需要记录出现的每个错误,但同时这不应阻塞流,因此在这种情况下,我们可以同时记录和返回消息。

2- async/await 编程中线程管理的好处

我们知道,在正常的编程(阻塞)中,即使我们有不同的流(两个流没有任何依赖关系),每一行代码都会阻塞它之后的所有内容,直到它完成该过程。但是在 async/await 编程中,应用程序不会阻塞这个线程,换句话说,他们会释放它来做另一项工作,当函数完成工作时,任何空闲线程都会处理响应。

C# async 和 await:我们为什么需要它们?