我试图在任务并行库中找到Task.WaitAll(..)。
我正在使用以下代码运行测试以尝试模拟两个任务,一个将比指定的等待时间(10秒)运行更长时间(10秒),一个运行更少(3秒)超过指定的等待时间。指定的时间是5秒。我使用的代码如下:
Task<int>[] tasks = new Task<int>[]
{
Task.Factory.StartNew<int>(()=>
{
Thread.Sleep(10000);
return 1;
}),
Task.Factory.StartNew<int>(()=>
{
Thread.Sleep(3000);
return 2;
})
};
TimeSpan timeSpan = new TimeSpan(0, 0, 5);
Task.WaitAll(tasks,timeSpan);
int[] results = new int[tasks.Length];
for(int i = 0; i < tasks.Length;i++)
{
Console.WriteLine(tasks[i].Result);
}
就timeSpan而言,我也试过直接传入5000而不是timeSpan变量,但它无法正常工作。我得到以下输出:
1
2
我希望只得到以下输出,因为另一个线程的执行时间超过了预期的等待时间。
1
我误解了这个,或者做错了吗?
答案 0 :(得分:11)
虽然Task.Delay是您通常想要使用的(因此您不会在睡眠期间浪费线程),但您的问题实际上与此无关。
这里发生的是,当您打印结果时,您将访问每项任务的结果属性。任务完成时阻止,因此您在WaitAll中等待5秒,然后在打印出10秒任务的结果时再等待5秒。
根据您声明的意图,您需要在访问结果之前检查任务状态,因为您的意图不是阻止它,而只是在碰巧已经完成时将其打印出来:
int[] results = new int[tasks.Length];
for (int i = 0; i < tasks.Length; i++)
{
if (tasks[i].IsCompleted)
{
Console.WriteLine(tasks[i].Result);
}
}
顺便说一句,你可以在结果&#39;上显示&#39;是原始代码中发生的事情,只需添加一些简单的时间检查(例如,使用秒表,就像这样)
Task<int>[] tasks = new Task<int>[]
{
Task.Factory.StartNew<int>(()=>
{
Thread.Sleep(10000);
return 1;
}),
Task.Factory.StartNew<int>(()=>
{
Thread.Sleep(3000);
return 2;
})
};
TimeSpan timeSpan = new TimeSpan(0, 0, 5);
var stopwatch = Stopwatch.StartNew();
Task.WaitAll(tasks, timeSpan);
Console.WriteLine("WaitAll took {0} seconds", stopwatch.Elapsed.TotalSeconds);
int[] results = new int[tasks.Length];
for (int i = 0; i < tasks.Length; i++)
{
stopwatch = Stopwatch.StartNew();
Console.WriteLine(tasks[i].Result);
Console.WriteLine("Printing result took {0} seconds", stopwatch.Elapsed.TotalSeconds);
}
这会产生控制台输出:
WaitAll took 4.9996961 seconds
1
Printing result took 5.0050012 seconds
2
Printing result took 0.0004338 seconds
答案 1 :(得分:3)
不要在任务中使用Thread.Sleep。 Task
调度程序不保证每个任务一个线程,而休眠可能会影响其他任务(请参阅Task is ignoring Thread.Sleep)。请改用Task.Delay()。
答案 2 :(得分:0)
尝试将时间跨度转换为
TimeSpan span = new TimeSpan(0, 0, 0, 10, 0);
//TimeSpan(Days, hours, minutes, seconds, milliseconds);