c# - C# 控制台应用程序中的单线程异步/等待

标签 c# async-await concurrency task

默认情况下,在控制台应用程序中,异步任务将在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/

相关文章:

c# - ID一次性接口(interface)

asp.net - 异步/等待、TPL、WCF 服务、Web API : So many choices

c# - 更改文本 block 中部分文本的颜色

c# - ASP.NET Repeater - 显示数据绑定(bind)列表<T> 的属性列表<T1>

c# - 从 OWIN 中间件返回异常

c++ - 从 C++ Windows 应用商店应用程序使用 sqlite-winrt

rust - 如何从返回异步的 Vec 闭包中加入_all?

c# - 检查控制变量后调用 AutoResetEvent.WaitOne

java - 如果一个线程执行完最后一条语句,一旦完成,它是否会像显式调用 return 一样保证死亡?

grails - 如果超时,是否有任何方法可以获取 PromiseList 的结果