默认情况下,在控制台应用程序中,异步任务将在ThreadPool上运行,这意味着多个任务可以在不同的线程上并行运行(如果您有多核处理器,也会这样做).

我如何才能禁止Task在我的控制台应用程序中并行运行(不使用互斥体;我不想处理公平性问题并记住在任何地方锁定互斥体)?我希望一次只运行一个并发任务(即,我希望任务是并发的,但不是并行的).

我曾try 将线程池中的最大线程数设置为1,但线程池运行时的线程数不能少于CPU的核心数,因此无法正常运行.

推荐答案

您可以使用Stephen Cleary在AsyncExNuGet包中找到的Static AsyncContext类在控制台应用程序上安装单线程同步上下文:

AsyncContext.Run(async () =>
{
    await Foo();
    await Task.WhenAll(items.Select(async item =>
    {
        var result = await Bar(item);
        DoStuff(result);
    }));
    await FooBar();
});

AsyncContext.Run是一个阻塞调用,类似于Application.Run方法.它在当前线程上安装一个特殊的AsyncContextSynchronizationContext,就像Application.Run在UI线程上安装WindowsFormsSynchronizationContext一样.只要AsyncContext.Run委托内的所有await都具有默认配置,这意味着没有ConfigureAwait(false)附加到它们,则每个await之后的所有延续都将在控制台应用程序的主线程上运行.Your代码将是单线程的.任何内置的异步方法可能仍然在幕后使用ThreadPool个线程来完成它们的工作,但是your代码不会观察到这些其他线程,也不会受到它们的影响.

AsyncContext.Run在异步action委托以及可能已在该委托内调用的任何async void方法完成时完成.相反,任何悬而未决的 ignition 和忘记任务都不会阻止AsyncContext.Run的完成,并且会被留在永远不完整的状态中.AsyncContext.Run完成后,AsyncContextSynchronizationContext将被卸载.SynchronizationContext.Current将恢复到其原始状态.

注意不要在委托中使用.Wait().Result,否则程序会死锁.如果您阻塞了执行代码的唯一线程,您的程序将陷入停顿.

Csharp相关问答推荐

SortedSet.IsSubsetOf未按预期工作

亚马逊Pinpoint C# SDK

ASP.NET Core 8 Cors标题未显示

Unity如何在PlayerPrefs中保存数据?

需要澄清C#的Clean Architecture解决方案模板的AuditableEntityInterceptor类

使用C#中的SDK在Microsoft Graph API上使用SubscribedSkus的问题

与C#中的Zip列表并行

发布用于Linux Ubuntu的C#应用程序

mocking对象的引发事件并作为用于调用方法的参数对象传递到那里

在调整大小的控件上绘制

如何使用C#中的主构造函数功能使用多个构造函数?

当用户右键单击文本框并单击粘贴时触发什么事件?

如何将端点(或с匹配请求并判断其路径)添加到BCL?

LINQ to Entities中的加权平均值

在Windows Plesk上发布ASP.NET Core 7 Web API-错误:无法加载文件或程序集';Microsoft.Data.SqlClient';

使用动态键从请求体反序列化JSON

ASP.NET MVC数据批注验证组复选框

C#Microsoft.CodeAnalysis.CSharp.Scriiting不等待并行.对于

SharpZipLib在文件名前加上目录名,生成tar.gz

使用LibraryImport在多个dll中导入相同的函数