简体   繁体   English

关于异步编程的简单问题

[英]Simple question about asynchronous programming

I have a simple question with async programming exposed by the following example:我对以下示例公开的异步编程有一个简单的问题:

foreach (var item in result)
{
    property1 = await GetObjectivesQueryable(ObjectiveType.Company, from, to).SumAsync(x => x.ValeurObjectif);
    property2 = await GetObjectivesQueryable(ObjectiveType.Company, new DateTime(DateTime.Now.Year, 1, 1), new DateTime(DateTime.Now.Year, 12, DateTime.DaysInMonth(DateTime.Now.Year, 12)).AddHours(23).AddMinutes(59).AddSeconds(59)).SumAsync(x => x.ValeurObjectif);
}

or the alternative:或替代方案:

foreach (var item in result)
{
    var task1 = GetObjectivesQueryable(ObjectiveType.Company, from, to).SumAsync(x => x.ValeurObjectif);
    var task2 = GetObjectivesQueryable(ObjectiveType.Company, new DateTime(DateTime.Now.Year, 1, 1), new DateTime(DateTime.Now.Year, 12, DateTime.DaysInMonth(DateTime.Now.Year, 12)).AddHours(23).AddMinutes(59).AddSeconds(59)).SumAsync(x => x.ValeurObjectif);

    await Task.WhenAll(task1, task2);

    property1 = task1.Result;
    property2 = task2.Result;
}

From what i understand about async programming the first example above will execute the first instruction, block the execution thread until it complete with the await keyword then fill the property.根据我对异步编程的了解,上面的第一个示例将执行第一条指令,阻塞执行线程,直到它使用 await 关键字完成,然后填充属性。 Then redoing this step for the second property.然后为第二个属性重做此步骤。

At the opposite the second example will asynchronously execute the both task and block the execution thread during the WhenAll instruction, then when both of the tasks are completed it will synchronously set property 1 and property 2.相反,第二个示例将在WhenAll指令期间异步执行两个任务并阻塞执行线程,然后当两个任务完成时,它将同步设置属性1和属性2。

So From my conclusion in this use case the second example is more performing.所以从我在这个用例中的结论来看,第二个例子表现得更好。

Do my knowledge about async in this case is right?在这种情况下,我对异步的了解是否正确?

Thanks in advance.提前致谢。

First point I would suggest is to differentiate between multithreading and multiprocessing.我建议的第一点是区分多线程和多处理。 Read here https://towardsdatascience.com/multithreading-and-multiprocessing-in-10-minutes-20d9b3c6a867 to understand more about it.阅读此处https://towardsdatascience.com/multithreading-and-multiprocessing-in-10-minutes-20d9b3c6a867以了解更多信息。

You are using language provided constructs to make it possible for the OS to process two units of work in parallel.您正在使用语言提供的结构来使操作系统能够并行处理两个工作单元。 Please do not call it multi-threading, although it is relevant it implies you are in control of lot more factors than you can in parallel processing constructs like async and await.请不要将其称为多线程,尽管它是相关的,但这意味着您可以控制比异步和等待等并行处理结构更多的因素。 In fact, this is why we still have explicit constructs for threading present in c#, such as BackgroundWorkerThread, despite of success of async and await.事实上,这就是为什么我们在 c# 中仍然有显式的线程构造,例如 BackgroundWorkerThread,尽管 async 和 await 成功。

Largely your understanding is correct.很大程度上你的理解是正确的。 However it becomes accurate when you put underlying hardware into picture.但是,当您将底层硬件放入图片中时,它会变得准确。

Modern processors have multiple cores.现代处理器具有多个内核。 Which means it is much more convenient to have parallelly running units of work.这意味着并行运行的工作单元要方便得多。 When you write your code using async and await, not necessarily it is going to get processed in parallel.当您使用 async 和 await 编写代码时,不一定会并行处理。 It depends upon lots of other factors including operating system's state, number of threads in the pool, available cores that can pick up subsequent task, other processes running in parallel etc.它取决于许多其他因素,包括操作系统的状态、池中的线程数、可以执行后续任务的可用内核、并行运行的其他进程等。

If you run async code on a processor which has only one core available for processing, effectively you are running blocking code since there is simply now way to have multiple instructions run in parallel without incurring cost of suspending one thread and loading another into memory - it might in fact become much slower than a simple blocking code that does not require context switching.如果您在只有一个内核可用于处理的处理器上运行异步代码,那么实际上您正在运行阻塞代码,因为现在有一种方法可以让多条指令并行运行,而不会产生挂起一个线程并将另一个线程加载到内存中的成本 - 它实际上可能比不需要上下文切换的简单阻塞代码慢得多。

With async and await you are simply paving way for multiprocessing if everything else aligns.使用 async 和 await 你只是为多处理铺平了道路,如果其他一切都对齐的话。 In most of the circumstances it does, but it has limits.在大多数情况下,它确实如此,但它有局限性。

Take a look at https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option?view=sql-server-ver16 to understand about maximum degree of parallelism.看看https://docs.microsoft.com/en-us/sql/database-engine/configure-windows/configure-the-max-degree-of-parallelism-server-configuration-option?view=sql- server-ver16了解最大并行度。

Also, this is not a new concept.此外,这不是一个新概念。 Its the c# language construct that abstracts away underlying complexity, without having you to do it - thats the key aspect of async and await.它是抽象出底层复杂性的 c# 语言结构,而无需您这样做——这是 async 和 await 的关键方面。

Despite being imprecise about the thread being blocked (which is incorrect as pointed out in the comments), you are correct.尽管对被阻止的线程不精确(正如评论中指出的那样不正确),但您是正确的。

While 'more performing' may mean many things, assuming that both operations are independent, Task.WhenAll option will finish earlier.虽然“性能更高”可能意味着很多事情,但假设这两个操作是独立的, Task.WhenAll选项将更早完成。

Having

var work1 = async () => await Task.Delay(1000);
var work2 = async () => await Task.Delay(2000);
await work1();
await work2();

will take 3 seconds, and将需要 3 秒,并且

await Task.WhenAll(work1(), work2());

will take 2 seconds.将需要 2 秒。

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

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