我目前正在研究TPL,并且已经提出了第一个已经没有产生预期输出的测试。我的代码是错误的还是预期的结果? 令我感到困惑的是,我正在开始20场比赛,除了等待之外什么都没做,我期待所有过程在5s内完成,需要更多,而且我的任务现在需要10秒而不是预期的5。 / p>
感谢您的帮助。
using System;
using System.Collections.Generic;
using System.Threading.Tasks;
namespace ConsoleApplication3Task
{
class Program
{
static void Main(string[] args)
{
var tasks = new List<Task<string>>();
for (var i = 0; i < 20; i++)
{
var task = Task.Factory.StartNew<string>((index) =>
{
var start = DateTime.UtcNow;
Task.Delay(TimeSpan.FromSeconds(5)).Wait();
var end = DateTime.UtcNow;
return string.Format("start={0}, duration={1} for task={2}", start.TimeOfDay, (end - start).TotalSeconds, index);
}, i);
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
tasks.ForEach((t) => Console.WriteLine(t.Result));
}
}
}
,输出为:
start=10:07:19.8499784, duration=9,4992059 for task=0
start=10:07:19.8489785, duration=9,5002058 for task=1
start=10:07:19.8499784, duration=9,4992059 for task=2
start=10:07:19.8499784, duration=9,4992059 for task=3
start=10:07:19.8499784, duration=9,4992059 for task=4
start=10:07:19.8489785, duration=9,5002058 for task=5
start=10:07:19.8489785, duration=9,5002058 for task=6
start=10:07:19.8489785, duration=9,5002058 for task=7
start=10:07:20.8481051, duration=5,0016351 for task=8
start=10:07:21.8492322, duration=5,5006984 for task=9
start=10:07:22.8483595, duration=5,5046991 for task=10
start=10:07:23.8494862, duration=5,4996981 for task=11
start=10:07:24.8486135, duration=5,0006344 for task=12
start=10:07:25.8497402, duration=5,0116365 for task=13
start=10:07:25.8507412, duration=5,0106355 for task=14
start=10:07:26.8488675, duration=5,0096356 for task=15
start=10:07:27.3499306, duration=5,0076366 for task=16
start=10:07:27.3499306, duration=5,0076366 for task=17
start=10:07:28.3530586, duration=5,0126368 for task=18
start=10:07:28.3530586, duration=5,0126368 for task=19
Press any key to continue . . .
答案 0 :(得分:3)
发生这种情况的原因是TPL(实际上是线程池)限制了您可以一次创建的线程数。你不应该改变这种行为,因为它会阻止一次性启动所有线程,这可能会导致问题。
但是, 可以通过使用ThreadPool.SetMinThreads()
来增加线程池中即时可用的线程数,如下所示:
ThreadPool.SetMinThreads(20, 20);
你应该几乎总是只为测试目的这样做。
如果您尝试将该行添加到程序的开头,它将使其按预期运行。
另请注意,实际延迟来自此行:
Task.Delay(TimeSpan.FromSeconds(5)).Wait();
.Wait()
导致线程池线程运行,并且它被限制,因此它不会立即启动。
您可以通过将该行更改为:
来验证这一点Thread.Sleep(TimeSpan.FromSeconds(5));
然后,即使不使用ThreadPool.SetMinThreads(20, 20);