代码:

public class Test
{
    public static void Main()
    {
        int threadCount = ThreadPool.ThreadCount;
        Console.WriteLine($"thread count : {threadCount}");
        
        ThreadPool.SetMinThreads(1, 2);
        Console.WriteLine(ThreadPool.SetMaxThreads(1, 2));
        
        List<Task> tlist = new();
        
        for (int i = 0; i < 3; i++)
        {
            Console.WriteLine($"repeat {i}");
            
            tlist.Add(Task.Run(() =>
            {
                threadCount = ThreadPool.ThreadCount;
                Console.WriteLine($"thread count : {threadCount}");
                return FuncAsync();
            }));
            Console.WriteLine($"repeat end {i}");
        }

        Task.WaitAll(tlist.ToArray());
    }

    public static async Task FuncAsync()
    {
        Console.WriteLine("FuncAsync");
    }
}

这段代码只有在"Run"with"Release"Build的情况下才能运行.

Debugging Running
Debug build work unwork
Release build work work

Screenshot

首先,对不起,我的台球英语能力…

我想知道当线程池的最大容量为1时,异步方法是如何工作的. 但我遇到了一些意想不到的错误.

When I try to run with debug build, thread pool start with already filling with 2 thread. Screenshot

So, there's no affordable thread in ThreadPool, then it doesn't work. Just stop infinitely ... Screenshot

但这种情况从一开始就不会发生,

  1. 使用调试版本进行调试
  2. 使用发布版本进行调试
  3. 使用发布版本运行

有人知道为什么会出现这种情况吗?

推荐答案

我没有安装Rider,但在VS中发生了很多相同的事情,所以我要回答这个问题.我想类似的事情也会发生在Rider身上.

在VS中,我们可以启动进程,然后执行调试-&>附加到进程...将调试器附加到我们启动的进程.点击Break,然后查看线程窗口,我们将看到:

Threads window

我们可以看到主线程(卡在Task.WaitAll)上)和辅助线程.如果我们双击辅助线程并查看"调用堆栈"窗口,我们会看到:

Call stack window

你可以看到有人拨打了Task.Run.值得注意的是,这不是您的代码.正在执行但不在运行时中的代码片段如下:

Microsoft.Extensions.DotNetDeltaApplier.dll!StartupHook.Initialize.AnonymousMethod__0() Unknown
Microsoft.Extensions.DotNetDeltaApplier.dll!StartupHook.ConnectToPipeAndSendCapabilitiesAsync()
Microsoft.Extensions.DotNetDeltaApplier.dll!Microsoft.Extensions.HotReload.ClientInitializationPayload.Write(System.IO.Stream stream)

DotNetDeltaApplier是什么?为谷歌干杯!从this answer人起:

VS2022将DLL加载到您的进程中:Microsoft.VisualStudio.Debugger.Runtime.NetCoreApp.dll,Microsoft.Extensions.DotNetDeltaApplier.dll等.如果您禁用热重新加载(项目属性/调试),它应该可以工作(这可能是使用COM在应用程序和重新加载的应用程序之间进行通信)

(我们可以看到它实际上使用的是命名管道,而不是COM,但这并不重要.)

因此,VS将一个额外的DLL加载到我们的进程中(使用startup hook),以支持热重新加载(在这种情况下,您更改源代码,这些更改将被修补到正在运行的可执行文件中).这个额外的DLL已经占用并阻塞了ThreadPool线程,这意味着线程池中没有剩余的线程可以运行您的Task.Run.

事实上,如果您直接在文件系统上找到并运行exe(而不是从VS启动),它将运行到完成.

Csharp相关问答推荐

如何使用Unity和MRTK3将手网添加到Hololens 2应用程序中

try 还原包时出错:Dapper已经为System.Data.SQLClient定义了依赖项''''

实体框架核心上是否支持使用NPGSQL的字符串聚合?

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

与C#中的Zip列表并行

不带身份的Blazor服务器.Net 8 Cookie身份验证

使用两个不同的枚举作为Switch语句中的CASE生成唯一值

如何使用C#获取FireStore中的列表输出文档

Docker Container中的HttpRequest后地址不可用

在IAsyncEnumerable上先调用,然后跳过(1)可以吗?

.NET:从XPath定位原始XML文档中的 node

在使用StringBuilder时,如何根据 colored颜色 设置为richTextBox中的特定行着色?

C#多键字典和TryGetValue

如何在onNext之前等待订阅者完成?

.NET8->;并发词典总是比普通词典快...怎么回事?[包含基准结果和代码]

如何使用LINQ在C#中填充列表列表?

将列表转换为带有逗号分隔字符串形式的值的字典

为什么我的UserControl没有加载到我的主窗口中?

反编译源代码时出现奇怪的字符

当我在Git中暂存文件更改时,它们会消失