我试图围绕整个并行编程概念,主要关注任务,所以我一直在尝试这种情况,比如说,最多 9 个并行任务将在随机时间段内执行它们的工作:
/// <remarks>
/// A big thank you to the awesome community of StackOverflow for
/// their advice and guidance with this sample project
/// http://stackoverflow.com/questions/5195486/
/// </remarks>
RNGCryptoServiceProvider random = new RNGCryptoServiceProvider();
byte[] buffer = new byte[4];
random.GetBytes(buffer);
// Creates a random number of tasks (not less than 2 -- up to 9)
int iteration = new Random(BitConverter.ToInt32(buffer, 0)).Next(2,9);
Console.WriteLine("Creating " + iteration + " Parallel Tasks . . .");
Console.Write(Environment.NewLine);
Dictionary<int, string> items = new Dictionary<int, string>();
for (int i = 1; i < iteration + 1; i++) // cosmetic +1 to avoid "Task N° 0"
{
items.Add(i, "Task # " + i);
}
List<Task> tasks = new List<Task>();
// I guess we should use a Parallel.Foreach() here
foreach (var item in items)
{
// Creates a random interval to pause the thread at (up to 9 secs)
random.GetBytes(buffer);
int interval = new Random(BitConverter.ToInt32(buffer, 0)).Next(1000, 9000);
var temp = item;
var task = Task.Factory.StartNew(state =>
{
Console.WriteLine(String.Format(temp.Value + " will be completed in {0} miliseconds . . .", interval));
Thread.Sleep(interval);
return "The quick brown fox jumps over the lazy dog.";
}, temp.Value).ContinueWith(t => Console.WriteLine(String.Format("{0} returned: {1}", t.AsyncState, t.Result)));
tasks.Add(task);
}
Task.WaitAll(tasks.ToArray());
但不幸的是,它们是按顺序处理的,而不是并行处理的。
如果你们能帮我解决这个问题,我会很高兴——也许我应该使用 Parallel.ForEach 而不是常规的?
如果有任何建议,我们将不胜感激。
编辑 两次更新代码示例以反射(reflect)评论者的贡献。
最佳答案
您在循环中 对每个任务调用 task.Result
...这意味着它会在创建下一个任务之前等待一个任务的结果.试试这个:
// Create all the tasks
foreach (var item in items)
{
// ... Create and start tasks as before
tasks.Add(task);
}
// Now wait for them all, printing the results
foreach (var task in tasks)
{
Console.WriteLine(task.AsyncState + " returned: " + task.Result);
}
现在这将阻塞立即创建的第一个任务 - 所以即使(比方说)第 5 个任务完成得更早,在第一个任务完成之前你不会看到任何结果......但它们将并行执行。
接下来您需要像这样更改循环:
foreach (var item in items)
{
var itemCopy = item;
// Use itemCopy in here instead of item
}
否则您将捕获循环变量,这被认为是有害的 ( part 1 ; part 2 )。
但是是的,您可能应该改用Parallel.ForEach
。不过,值得了解它之前失败的原因。
关于c# - 并行任务按顺序处理,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5195486/