c# - 并行任务按顺序处理

标签 c# parallel-processing task task-parallel-library

我试图围绕整个并行编程概念,主要关注任务,所以我一直在尝试这种情况,比如说,最多 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/

相关文章:

c# - 一个接口(interface)与 DI 的多种实现

c# - 服务器端 AsyncPattern 调用 SQL Server

python - 运行并行 KMeans 时为 "index N is out of bounds for axis 0 with size N",而顺序 KMeans 工作正常

c# - .Net Async ContinueWith VS 在任务中嵌入任务

C# TaskFactory 未完成所有迭代

properties - Gradle中任务的分组/继承属性

c# - OleDbParameter 的名称痴迷

c# - 不能将文本数据类型选为 DISTINCT,因为它不可比较

r - 如何并行化r中的外部函数?

c - 测量 CUDA 内核时的时间不同