debugging 为什么线程池在debug-build-run中以2个线程开始?

0sgqnhkj  于 2023-08-06  发布在  其他
关注(0)|答案(1)|浏览(89)

代码:

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");
    }
}

字符串
此代码仅在'release' build中'run'时才有效。
| | Debugging | Running |
| --|--| ------------ |
| 工作|使不工作| unwork |
| 工作|工作| work |
x1c 0d1x的数据
首先,对不起我的英语水平…
我特灵知道当线程池的最大容量为1时,异步方法是如何工作的。但我遇到了一些意想不到的错误。
当我尝试运行调试构建时,线程池开始时已经充满了2个线程。


所以,在ThreadPool中没有负担得起的线程,那么它就不能工作。只是无限地停止。。


但这种情况从来没有发生时,开始与,
1.使用调试版本进行调试
1.使用发布版本调试
1.使用发布版本运行
有人知道为什么会出现这种情况吗?

gz5pxeao

gz5pxeao1#

我没有安装Rider,但在VS中发生了很多相同的事情,所以我将对此做出回答。我认为类似的事情发生在骑士身上。
在VS中,我们可以启动进程,然后执行Debug -> Attach to Process...将调试器附加到我们启动的进程。点击Break,然后查看Threads窗口,我们看到:
x1c 0d1x的数据
我们可以看到主线程(它卡在Task.WaitAll)上)和辅助线程。如果我们双击工作线程并查看“调用堆栈”窗口,我们会看到:



你可以看到有人叫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
VS 2022将dll加载到进程中:Microsoft.VisualStudio.Debugger.Runtime.NetCoreApp.dll、Microsoft.Extensions.DotNetDeltaApplier.dll等。如果您禁用热重载(项目属性/调试),它应该工作(这可能是使用COM之间的应用程序和重载通信)
(We可以看到它实际上使用的是命名管道而不是COM,但这并不重要。)
所以VS已经加载了一个额外的DLL到我们的进程中(使用startup hook),以支持热重载(在那里你改变了源代码,这些变化被修补到一个正在运行的可执行文件)。这个额外的DLL占用并阻塞了一个ThreadPool线程,这意味着ThreadPool中没有剩余的线程来运行您的Task.Run
实际上,如果您直接在文件系统上找到并运行exe(而不是从VS启动),它将运行到完成。

相关问题