ebb*_*ebb 17 c# multithreading
代码:
static void DoIt(string name)
{
Console.WriteLine("Hello {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
Thread.Sleep(5000);
Console.WriteLine("Bye {0} | {1}", name, Thread.CurrentThread.ManagedThreadID);
}
static void Main()
{
Task.Factory.StartNew(() => DoIt("One"));
Task.Factory.StartNew(() => DoIt("Two"));
Task.Factory.StartNew(() => DoIt("Three"));
Task.Factory.StartNew(() => DoIt("Four"));
Task.Factory.StartNew(() => DoIt("Five"));
Task.Factory.StartNew(() => DoIt("Six"));
Task.Factory.StartNew(() => DoIt("Seven"));
Task.Factory.StartNew(() => DoIt("Eight"));
Task.Factory.StartNew(() => DoIt("Nine"));
Task.Factory.StartNew(() => DoIt("Ten"));
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
为什么它可以立即精确启动前3个任务,但是任务4启动需要5-10秒,在任务4启动后,任务5启动前需要5-10秒,依此类推.GC是做什么的吗?有人可以澄清一下发生了什么吗?
Ree*_*sey 18
为什么它可以立即精确启动前3个任务,但是任务4启动需要5-10秒,在任务4启动后,任务5启动前需要5-10秒,依此类推.GC是做什么的吗?有人可以澄清一下发生了什么吗?
默认情况下,第一次运行此命令时,ThreadPool将使用最小工作线程数分配.在安排了前4个任务之后,线程池将"加速"以便随着时间的推移处理更多,这就是您看到延迟的原因.
在我的系统(有8个核心)上,前8个是即时的,然后接下来的两个在一秒后启动.
在您的情况下,如果您第二次运行测试,则线程将立即启动.这是因为,在第一次运行之后,ThreadPool应该有足够的工作人员立即安排这个.
请尝试以下操作以查看此行为.如果您将SetMinThreads呼叫保留在原地,则会立即安排这些呼叫.如果你注释掉它,你会看到,第一次,它需要一段时间,但第二次通过(假设你等待线程完成),线程将立即运行.
static void DoIt(string name)
{
Console.WriteLine("Hello {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
Thread.Sleep(5000);
Console.WriteLine("Bye {0} | {1} - {2}", name, Thread.CurrentThread.ManagedThreadId, DateTime.Now);
}
static void Main()
{
int workerThreads, complete;
ThreadPool.GetMinThreads(out workerThreads, out complete);
Console.WriteLine(workerThreads);
// Comment out this line to see the difference...
// WIth this commented out, the second iteration will be immediate
ThreadPool.SetMinThreads(100, complete);
Action run = () =>
{
for (int i = 0; i < 20; ++i)
{
int tmp = i;
Task.Factory.StartNew(() => DoIt(tmp.ToString()));
}
};
run();
Console.WriteLine("Press a key to run again...");
Console.ReadKey();
run();
Console.WriteLine("Press a key to exit...");
Console.ReadKey();
}
Run Code Online (Sandbox Code Playgroud)
请注意,这种行为实际上与整个TPL没什么关系 - 它更多是默认TaskScheduler使用的,只是将任务传递给了ThreadPool.例如,如果你LongRunning在StartNew()调用中使用提示设置这些线程,它们都会立即启动(因为默认调度程序将设置一个新的专用线程并立即执行它).
任务没有减慢,它们被任务并行库排队.CLR知道您的计算机上有多少逻辑核心可用; TPL线程池使用此信息来确定要提供的工作线程数.在您的情况下,您可能有四个逻辑核心; 为主线程(Main()正在运行)取一个三个核心(和三个线程池工作者)仍然执行任务.