C# C-理解异步/等待

C# C-理解异步/等待,c#,asynchronous,async-await,C#,Asynchronous,Async Await,异步编程的C文档说明: 对于CPU绑定的代码,您将等待在后台线程上使用Task.Run方法启动的操作 等待关键字是魔术发生的地方。它将控制权交给wait执行的方法的调用者,并最终允许UI具有响应性或服务具有弹性 当应用wait关键字时,它将暂停调用方法并将控制权返回给调用方,直到等待的任务完成 考虑到这一点,我测试了一些CPU绑定的代码,发现比特币块散列似乎非常现代,很难尝试并准确理解应用async/await时发生的情况: 范例 好的,对于那些对比特币及其工作原理感兴趣的更精明的人来说,这不是

异步编程的C文档说明:

对于CPU绑定的代码,您将等待在后台线程上使用Task.Run方法启动的操作

等待关键字是魔术发生的地方。它将控制权交给wait执行的方法的调用者,并最终允许UI具有响应性或服务具有弹性


当应用wait关键字时,它将暂停调用方法并将控制权返回给调用方,直到等待的任务完成

考虑到这一点,我测试了一些CPU绑定的代码,发现比特币块散列似乎非常现代,很难尝试并准确理解应用async/await时发生的情况:

范例

好的,对于那些对比特币及其工作原理感兴趣的更精明的人来说,这不是真正的比特币哈希算法,但它是SHA256SHA256data+nonce,所以对于这个例子来说已经足够困难了

期望与现实

我以为计算散列。。。将立即打印到控制台,然后在最终找到哈希时打印结果

实际上,在找到散列之前,不会向控制台打印任何内容

问题:

我的理解或代码哪里出错了?

这是因为你在等待它

我认为理解它的最好方法就是把异步代码想象成一个并发运行的代码块,但一旦你等待它,你就会说:我现在需要这个值,如果你不等待,除非我得到它,否则我不会继续进行,然后你正在处理一个可能处于不完整状态的任务。

这是因为你在等待它

我认为理解它的最好方法就是把异步代码想象成一个并发运行的代码块,但一旦你等待它,你就会说:我现在需要这个值,如果你不等待,除非我得到它,否则我不会继续进行,然后您正在处理一个可能处于不完整状态的任务。

此处:string result=await HashAsyncGuid.NewGuid.ToByteArray,4

您正在挂起Main中的caller方法,等待的调用完成后,它将继续

控制台的打印是在同一个调用方方法中完成的,因此一旦HashAsync完成,您将看到正在计算的哈希…

此处:string result=Wait HashAsyncGuid.NewGuid.ToByteArray,4

您正在挂起Main中的caller方法,等待的调用完成后,它将继续

控制台的打印是在同一个调用者方法中完成的,因此一旦HashAsync完成,您将看到正在计算的哈希…

因为您在HashAsync上调用Wait,控件将被交给调用者,在这种情况下是.NET Framework本身,它调用了您的主方法

我认为了解其工作原理的最简单方法是将从HashAsync返回的任务分配给变量,但不要等到Console.WriteLine之后再等待它:

通过此更改,一旦调用HashAsync,它将使用Task将工作推送到后台。运行并返回任务以观察该工作的进度。但因为您并没有等待它,所以Main方法将继续执行和计算哈希。。。将被打印出来。只有在调用await resultTask后,该控件才会返回给调用Main的人,并且执行将被挂起。

因为您在HashAsync上调用await,所以该控件将被交给调用方,在这种情况下,.NET Framework本身调用了您的Main方法

我认为了解其工作原理的最简单方法是将从HashAsync返回的任务分配给变量,但不要等到Console.WriteLine之后再等待它:


通过此更改,一旦调用HashAsync,它将使用Task将工作推送到后台。运行并返回任务以观察该工作的进度。但因为您并没有等待它,所以Main方法将继续执行和计算哈希。。。将被打印出来。只有在您调用Wait resultTask控件后,它才会返回给调用Main的用户,并且执行将被挂起。

当执行线程或UI线程执行以Wait开头的代码行时,UI线程将自动解锁,并等待操作完成,同时用户可以与UI交互,当异步操作完成一段时间后,代码将立即开始执行,如果它首先离开的话

更新

在C7.1中,main方法也可以是异步的,异步wait可以用这种方式使用

  class Program
  {
      public static async Task Main(string[] args)
      {
         await Task.Run(async () =>
         {
            MyAsyncFunc();
         });
         Console.WriteLine("done");
         Console.ReadLine();
      }

    static async Task MyAsyncFunc()
     {
        await Task.Delay(3000);
     }
  }

当执行线程或UI线程执行一行以wait开头的代码时,UI线程将自动取消阻止并等待操作完成,同时用户可以与UI交互,在异步操作完成一段时间后,代码将立即开始执行(如果先不执行)

Upda te

在C7.1中,main方法也可以是异步的,异步wait可以用这种方式使用

  class Program
  {
      public static async Task Main(string[] args)
      {
         await Task.Run(async () =>
         {
            MyAsyncFunc();
         });
         Console.WriteLine("done");
         Console.ReadLine();
      }

    static async Task MyAsyncFunc()
     {
        await Task.Delay(3000);
     }
  }


这是因为您在打印前等待。好吧,您正在等待它。@SLaks当应用wait关键字时,它将暂停调用方法并将控制权返回给调用方,直到等待的任务完成。-在我看来,这意味着等待的方法被挂起,主方法获得控制权,直到等待的方法完成,最后,Console.WriteLineresult解析并完成我知道,我可能完全不懂它暂停了调用方法,即使用async的方法,并将控制权返回给async方法的调用方,不管调用了什么方法Imagine,Wait将方法分为前后两部分。如果您熟悉javascript,可以想象一些ajax查询总是包含“then…”的内容。wait之后的Part是这样的“then”延续,但是按顺序写入,没有回调地狱。这是因为您在打印之前等待。好吧,您正在等待它。@SLaks当应用wait关键字时,它将暂停调用方法并将控制权交还给调用方,直到等待的任务完成。-在我看来,这意味着等待的方法被挂起,主方法获得控制权,直到等待的方法完成,最后,Console.WriteLineresult解析并完成我知道,我可能完全不懂它暂停了调用方法,即使用async的方法,并将控制权返回给async方法的调用方,不管调用了什么方法Imagine,Wait将方法分为前后两部分。如果您熟悉javascript,可以想象一些ajax查询总是包含“then…”的内容。wait之后的部分是这样的“then”延续,但是是按顺序编写的,没有回调地狱。如果是这样,这与非异步/wait代码有什么不同……我觉得我错过了一些东西。@series0ne在UI线程上尝试它,一个线程将阻塞挂起UI,另一个线程将返回UI。如果是这样,这与非异步/等待代码有何不同……我觉得我错过了一些东西。@系列0可以在UI线程上尝试,一个线程将阻止挂起UI,另一个线程将返回UI。在控制台应用程序中如何?在控制台应用程序中,主方法不能是异步的,因此您必须运行任务并手动使其等待。但是,根据C7.1中的介绍,我的主要方法是async,C7.1确实支持async in Main方法,要实现目标,可以像等待任务一样执行;它将产生所需的结果。我自己已经测试过,控制台将首先打印计算哈希值。在控制台应用程序中如何?在控制台应用程序中,主方法不能是异步的,因此您必须运行任务并手动使其等待。但是,根据C7.1中的介绍,我的主要方法是async,C7.1确实支持async in Main方法,要实现目标,可以像等待任务一样执行;它将产生所需的结果。我自己已经测试过了,控制台将首先打印计算哈希
  class Program
  {
      public static async Task Main(string[] args)
      {
         await Task.Run(async () =>
         {
            MyAsyncFunc();
         });
         Console.WriteLine("done");
         Console.ReadLine();
      }

    static async Task MyAsyncFunc()
     {
        await Task.Delay(3000);
     }
  }