默认情况下,在控制台应用程序中,异步任务将在ThreadPool
上运行,这意味着多个任务可以在不同线程上并行运行(如果您有多核处理器,则可以)。
如何禁止任务
在我的控制台应用程序中并行运行(不使用互斥体;我不想处理公平问题并记住在各处锁定互斥体) ?我希望一次只运行一项并发任务(即我希望这些任务是并发的,但不是并行的)。
我尝试将 ThreadPool 中的最大线程数设置为 1,但 ThreadPool 运行的线程数不能少于 CPU 核心数,因此这不起作用。
最佳答案
您可以使用 AsyncEx 中的静态 AsyncContext
类在控制台应用程序上安装单线程同步上下文。 Stephen Cleary 的 NuGet 包:
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
安装 WindowsFormsSynchronizationContext
一样。在 UI 线程上。只要 AsyncContext.Run
委托(delegate)内的所有 await
都具有默认配置,即没有 ConfigureAwait(false)
附加到它们上,每个 await
之后的所有延续都将在控制台应用程序的主线程上运行。 您的代码将是单线程的。任何内置异步方法可能仍会在后台使用 ThreadPool 线程来完成其工作,但您的代码不会观察这些其他线程,也不会受到影响由他们。
当异步 action
委托(delegate)完成时,AsyncContext.Run
以及可能在委托(delegate)内调用的任何 async void
方法也完成。相反,任何待处理的即发即弃任务都不会阻止 AsyncContext.Run 完成,并且会处于永远不完整的状态。 AsyncContext.Run
完成后,AsyncContextSynchronizationContext
将被卸载。 SynchronizationContext.Current
恢复到原来的状态。
注意不要在委托(delegate)内部使用.Wait()
或.Result
,否则你的程序将死锁。如果您阻塞执行代码的唯一线程,您的程序将逐渐停止。
关于c# - C# 控制台应用程序中的单线程异步/等待,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/77004994/