C#,为什么简单等待Task.Delay(1);“启用"并行执行?

编程入门 行业动态 更新时间:2024-10-25 18:23:19
本文介绍了C#,为什么简单等待Task.Delay(1);“启用"并行执行?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述

我想问一下关于以下代码的简单问题:

I would like to ask simple question about code bellow:

static void Main(string[] args) { MainAsync() //.Wait(); .GetAwaiter().GetResult(); } static async Task MainAsync() { Console.WriteLine("Hello World!"); Task<int> a = Calc(18000); Task<int> b = Calc(18000); Task<int> c = Calc(18000); await a; await b; await c; Console.WriteLine(a.Result); } static async Task<int> Calc(int a) { //await Task.Delay(1); Console.WriteLine("Calc started"); int result = 0; for (int k = 0; k < a; ++k) { for (int l = 0; l < a; ++l) { result += l; } } return result; }

此示例以同步方式运行Calc函数.当行"//等待Task.Delay(1);"时,将不加注释,将以并行方式执行Calc函数.

This example runs Calc functions in synchronous way. When the line "//await Task.Delay(1);" will be uncommented, the Calc functions will be executed in a parallel way.

问题是:为什么通过添加简单的等待,然后使Calc函数异步?我了解异步/等待对的要求.我问的是,在函数的开头添加简单的等待延迟时,到底发生了什么.整个Calc函数然后被识别为在另一个线程中运行,但是为什么呢?

The question is: Why, by adding simple await, the Calc function is then async? I know about async/await pair requirements. I'm asking about what it's really happening when simple await Delay is added at the beginning of a function. Whole Calc function is then recognized to be run in another thread, but why?

当我在代码中添加线程检查时:

When I added a thread checking to code:

static async Task<int> Calc(int a) { await Task.Delay(1); Console.WriteLine(Thread.CurrentThread.ManagedThreadId); int result = 0; for (int k = 0; k < a; ++k) { for (int l = 0; l < a; ++l) { result += l; } } return result; }

有可能(在控制台中)看到不同的线程ID.如果等待延迟",则返回"0".行被删除,对于Calc函数的所有运行,线程ID始终相同.在我看来,它证明了等待之后的代码可以(可以)在不同的线程中运行.这就是代码更快(当然,我认为是这样)的原因.

it is possible to see (in console) different thread id's. If "await Delay" line is deleted, the thread id is always the same for all runs of Calc function. In my opinion it proves that code after await is (can be) runned in different threads. And it is the reason why code is faster (in my opinion of course).

推荐答案

重要的是要了解 async 方法的工作方式.

It's important to understand how async methods work.

首先,它们开始在同一线程上同步运行,就像其他所有方法一样.没有该 await Task.Delay(1)行,编译器将警告您该方法将完全同步. async 关键字本身不会使您的方法异步.它只是允许使用 await .

First, they start running synchronously, on the same thread, just like every other method. Without that await Task.Delay(1) line, the compiler will have warned you that the method would be completely synchronous. The async keyword doesn't, by itself, make your method asynchronous. It just enables the use of await.

魔术发生在第一个 await 上,它作用于不完整的 Task .此时,方法返回.它会返回一个 Task ,您可以用来检查该方法的其余部分何时完成.

The magic happens at the first await that acts on an incomplete Task. At that point the method returns. It returns a Task that you can use to check when the rest of the method has completed.

因此,当您有 await Task.Delay(1)时,该方法将在该行返回,从而允许您的 MainAsync 方法移至下一行并开始执行下次调用 Calc .

So when you have await Task.Delay(1) there, the method returns at that line, allowing your MainAsync method to move to the next line and start the next call to Calc.

Calc 的延续如何运行( await Task.Delay(1)之后的所有内容)取决于是否存在同步上下文".例如,在ASP.NET(不是Core)或UI应用程序中,同步上下文控制继续的运行方式以及继续运行的顺序.在UI应用程序中,它应位于从其开始的同一线程上.在ASP.NET中,它可能是一个不同的线程,但仍然是一个接一个的线程.因此,无论哪种情况,您都不会看到任何并行性.

How the continuation of Calc runs (everything after await Task.Delay(1)) depends on if there is a "synchronization context". In ASP.NET (not Core) or a UI application, for example, the synchronization context controls how the continuations run and they would run one after the other. In a UI app, it would be on the same thread it started from. In ASP.NET, it may be a different thread, but still one after the other. So in either case, you would not see any parallelism.

但是,因为这是一个控制台应用程序,没有同步上下文,所以只要 Task.Delay(1)完成.这意味着每个延续都可以并行发生.

However, because this is a console app, which does not have a synchronization context, the continuations happen on any ThreadPool thread as soon as the Task from Task.Delay(1) completes. That means each continuation can happen in parallel.

同样值得注意的是:从C#7.1开始,您可以使您的 Main 方法为 async ,从而无需您的 MainAsync 方法:

Also worth noting: starting with C# 7.1 you can make your Main method async, eliminating the need for your MainAsync method:

static async Task Main(string[] args)

更多推荐

C#,为什么简单等待Task.Delay(1);“启用"并行执行?

本文发布于:2023-11-08 16:19:56,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1569866.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:简单   Task   quot   Delay

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!