gpt4 book ai didi

c# - 当 ThreadPool 中的事件线程数大于 ThreadPool.GetMinThreads() 时启动任务

转载 作者:太空狗 更新时间:2023-10-30 01:29:13 25 4
gpt4 key购买 nike

摘自对我之前一个问题的回答( Task.Factory.StartNew starts with a great delay despite having available threads in threadpool ):

"It's not the MAX worker threads value you need to look at - it's the MIN value you get via ThreadPool.GetMinThreads(). The max value is the absolute maximum threads that can be active. The min value is the number to always keep active. If you try to start a thread when the number of active threads is less than max (and greater than min) you'll see a 2 second delay."

所以,我准备了一个示例代码来测试它:

ThreadPool.GetMinThreads() 为我的机器返回“8”,我在本地机器上运行代码。

我的代码如下所示:

        Task task = null;

int workerThreads = 0;
int completionPortThreads = 0;



ThreadPool.GetMinThreads(out workerThreads, out completionPortThreads);
Logger.WriteInfo(LogCode.EMPTY_INFO, workerThreads.ToString());**returns "8"**

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread1");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread1");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread2");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread2");
while (true)
{
DoSomthing();
}
});
;
Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread3");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread3");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread4");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread4");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread5");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread5");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread6");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread6");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread7");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread7");
while (true)
{
DoSomthing();
}
});


Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread8");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread8");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread9");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread9");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread10");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread10");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread11");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread11");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread12");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread12");
while (true)
{
DoSomthing();
}
});

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread13");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread13");
while (true)
{
DoSomthing();
}
});


private void DoSomthing()
{
int j = 1;
for (int i = 0; i < 2000; i++)
{
j = i * i;
}
}

Logger 类只使用 log4net.dll。因此,ThreadPool.GetMinThreads() 为我的机器返回 8。最小值是始终保持事件状态的数字。如果您尝试在事件线程数小于最大值(且大于最小值)时启动线程,您将看到 2 秒的延迟。

因此,对于线程号 9 等等:

Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread9");
task = Task.Factory.StartNew(() =>
{
Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread9");
while (true)
{
DoSomthing();
}
});

我希望在

之间有 2 秒的延迟
Logger.WriteInfo(LogCode.EMPTY_INFO, "before thread9");

 Logger.WriteInfo(LogCode.EMPTY_INFO, "after thread9");

因为当事件线程数大于 min(大于 8)时,我尝试启动一个线程(从线程池)。实际结果是只有几毫秒的延迟(不到半秒)对于所有线程 9 到 13。

为什么至少没有2秒的延迟?我的意思是,我的线程池中的所有事件线程都很忙,并且对于线程 9,它需要分配另一个线程,所以应该有延迟。

在编写此示例应用程序后,我不确定我上一个问题中的场景。

最佳答案

这里有几个问题。

  • 首先是,您正在使用您可能不应该使用的Task.Factory.StartNew,在大多数情况下您应该使用更现代的Task.Run 有很多关于此的问题和博客。

  • 其次,您引用的问题引用的文档比当前框架更旧。文档已更改。它曾经规定了创建线程的毫秒延迟。

  • 第三,任务不是线程。

我的理解是task scheduler(看你用的是哪个)用启发式的方式来判断是否要给你一个线程在每个类别中,并没有任意的毫秒延迟。

文档目前所说的是。

ThreadPool Class

The thread pool provides new worker threads or I/O completion threads on demand until it reaches the minimum for each category. When a minimum is reached, the thread pool can create additional threads in that category or wait until some tasks complete.

事实是,如果您依赖任务调度程序的典型行为以特定速度分配线程,那么您肯定做错了什么。这是一个实现细节,可能会因版本而异。充其量您可以增加最少的线程数,但任务调度程序的工作是在很大程度上将您从这一级别的细节中抽象出来。它旨在为您做最好的事情。

如果您需要一定数量的线程,要么构建您自己的任务调度器,要么创建您自己的线程并一起跳过任务调度器

关于c# - 当 ThreadPool 中的事件线程数大于 ThreadPool.GetMinThreads() 时启动任务,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/53607942/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com