默认情况下,在控制台应用程序中,异步任务将在
ThreadPool
上运行,这意味着多个任务可以在不同线程上并行运行(如果您有多核处理器,则将会运行)。
如何禁止
Task
在我的控制台应用程序中并行运行(不使用互斥体;我不想处理公平问题并记住在各处锁定互斥体)?我希望一次只运行一项并发任务(即我希望这些任务是并发的,但不是并行的)。
我尝试将 ThreadPool 中的最大线程数设置为 1,但是 ThreadPool 运行的线程数不能少于 CPU 核心数,因此这不起作用。
您可以使用 Stephen Cleary 的
AsyncExNuGet 包中找到的静态
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
方法。它在当前线程上安装一个特殊的 SynchronizationContext
,就像 Application.Run
在 UI 线程上安装一个 WindowsFormsSynchronizationContext
一样。只要您直接在 await
委托内进行 AsyncContext.Run
一切操作(即没有 ConfigureAwait(false)
),每个 await
之后的所有延续都将在控制台应用程序的主线程上运行。 您的代码将是单线程的。任何内置的异步方法可能仍然在底层使用 ThreadPool
线程来完成它们的工作,但是 你的 代码不会观察这些其他线程,也不会受到它们的影响。
注意不要在任何地方使用
.Wait()
或 .Result
,否则你的代码将会死锁。如果您阻塞执行代码的单个线程,您的程序将停止运行。