英文:
I have a question about C#'s worker threads
问题
在这段代码中,当你使用 await Task.Delay(5000);
时,Console.WriteLine("START TestSemaPhoreSlims:ID[" + ids + "]...
这行代码会立即执行,没有任何延迟。
然而,当你使用 Thread.Sleep(5000);
时,从日志中可以观察到延迟,延迟从 START TestSemaPhoreSlims:ID[ID:7] workerThreads>>>2040: times>>>16-06-44
开始。期望的行为是 Console.WriteLine
语句应该立即执行,没有任何延迟。
希望这样能解释清楚问题。如果有进一步的问题,请告诉我。
英文:
In this code, when you use await Task.Delay(5000);
, the line Console.WriteLine("START TestSemaPhoreSlims:ID[" + ids + "]...
is executed without any delay.
However, when you use Thread.Sleep(5000);
, you observe a delay in the logs starting from "START TestSemaPhoreSlims:ID[ID:7] workerThreads>>>2040: times>>>16-06-44"
. The expected behavior is that the Console.WriteLine
statement should execute immediately without any delay.
I hope this clarifies the issue. Let me know if you have any further questions.
public class SemaPhoreTest1s
{
public SemaPhoreTest1s()
{
for (int i = 1; i <= 10; i++)
{
int idnums = i;
Task.Run(() => TestSemaPhoreSlims("ID:" + idnums));
}
Console.WriteLine("MAIN THREAD:" + Thread.CurrentThread.ManagedThreadId);
Console.ReadLine();
}
public async void TestSemaPhoreSlims(string ids)
{
int workerThreads, completionPortThreads;
ThreadPool.GetAvailableThreads(out workerThreads, out completionPortThreads);
Console.WriteLine("START TestSemaPhoreSlims:ID[" + ids + "] workerThreads>>>" + workerThreads + ": times>>>" + DateTime.Now.ToString("HH-mm-ss"));
Thread.Sleep(5000);
//await Task.Delay(5000);
}
}
MAIN THREAD:1
START TestSemaPhoreSlims:ID\[ID:2\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:1\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:5\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:4\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:3\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:6\] workerThreads\>\>\>2041: times\>\>\>16-06-43
START TestSemaPhoreSlims:ID\[ID:7\] workerThreads\>\>\>2040: times\>\>\>16-06-44
START TestSemaPhoreSlims:ID\[ID:8\] workerThreads\>\>\>2039: times\>\>\>16-06-45
START TestSemaPhoreSlims:ID\[ID:9\] workerThreads\>\>\>2038: times\>\>\>16-06-46
START TestSemaPhoreSlims:ID\[ID:10\] workerThreads\>\>\>2037: times\>\>\>16-06-47
答案1
得分: 2
ThreadPool
以定义的工作线程数量启动。您可以通过调用ThreadPool.GetMinThreads
方法来获取该信息,该方法返回工作线程和完成端口线程的最小值。
线程池在运行时会增加工作线程的数量,但这需要一些时间。当您在同一个进程中一遍又一遍地重复执行代码时,您可以观察到这一点。此外,线程池会在工作线程未被使用一段时间后终止它们。
要从一开始就运行所有任务,请将最小工作线程数设置为您满意的值(这里设置为10就足够了)。
// 在运行代码之前设置
ThreadPool.SetMinThreads(10, 1);
现在每个任务都应该按您的期望运行。
如果您想要查看工作线程数量如何变化,可以打印ThreadPool.ThreadCount
的值。
为什么在使用Task.Delay
时不会发生这种情况?
因为使用Task.Delay
时没有线程(用于该延迟)。在幕后,有一个状态机,当延迟结束时,调度程序将再次激活该状态机。
英文:
The ThreadPool
starts with an amount of worker threads defined. You can get that information by calling ThreadPool.GetMinThreads
method, which returns the minimum for worker- and completionPort threads.
The thread pool increases the number of worker threads while running but it takes some time to do so. You can watch this, when you repeat the code again and again within the same process. Also the thread pool will kill worker threads after an amount of time when they are not used.
To get all tasks running from the start set the minimum worker threads to the value you are satisfied with (here 10 will be enough).
// set before you run your code
ThreadPool.SetMinThreads( 10, 1 );
Now every task should run as you expected.
When you want to watch how the number of worker threads changes you can print out the Threadpool.ThreadCount
value.
Why does this not happen with Task.Delay
?
Because with Task.Delay
there is no Thread (for that delay). Behind the scenes there is a state machine that will be activated again from the Scheduler when the delay is over.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论