C#中的任务示例

时间:2013-10-07 12:55:59

标签: c# parallel-processing

我开始在C#中使用Tasks。 我正在尝试执行此代码。

    private static void CreateSubtask() {

        Task<Int32[]> parent = Task.Run(() =>
        {
            var results = new Int32[3];
            new Task(() => results[0] = 0,
                TaskCreationOptions.AttachedToParent).Start();
            new Task(() => results[1] = 1,
                TaskCreationOptions.AttachedToParent).Start();
            new Task(() => results[2] = 2,
                TaskCreationOptions.AttachedToParent).Start();
            return results;
        });
        var finalTask = parent.ContinueWith(
           parentTask =>
           {
               foreach (int i in parentTask.Result)
                   Console.WriteLine(i);
           });
        finalTask.Wait();
    }

finalTask​​仅在父任务完成后运行,父任务在完成所有三个子节点后结束。您可以使用它来创建非常复杂的Task层次结构,它将完成您指定的所有步骤。

我从执行中得到的是三行说:

0 0 0

我原以为他们是

0 1 2

我是对的吗?

3 个答案:

答案 0 :(得分:6)

Task.Run与父任务一起使用会抑制AttachedToParent对子任务的影响:http://blogs.msdn.com/b/pfxteam/archive/2011/10/24/10229468.aspx

改为使用Task.Factory.StartNew

答案 1 :(得分:4)

问题是你的parent任务在完成启动其他三个任务时完成,而不是在其他三个任务完成时完成。

相反,您可以使用Task.WhenAll创建一个任务,该任务将在所有其他任务完成后完成。

使程序更加惯用的任务代码的另一个变化是让每个内部任务返回自己的值,而不是改变某些共享状态,只是因为在多线程环境中处理共享状态可能更难以推理。

var parent = Task.WhenAll(Task.Run(() => 0),
    Task.Run(() => 1),
    Task.Run(() => 2));
var finalTask = parent.ContinueWith(t =>
    {
        foreach (int n in t.Result)
            Console.WriteLine(n);
    });
finalTask.Wait();

答案 2 :(得分:0)

你只是开始你的三个子任务,但不等待它们完成。像这样适应它,例如:

            var task1 = new Task(() => results[0] = 0,
                TaskCreationOptions.AttachedToParent);
            var task2 = new Task(() => results[1] = 1,
                TaskCreationOptions.AttachedToParent);
            var task3 = new Task(() => results[2] = 2,
                TaskCreationOptions.AttachedToParent);

            task1.Start();
            task2.Start();
            task3.Start();

            task1.Wait();
            task2.Wait();
            task3.Wait();

另请注意,对于您当前的代码,仍然可以显示0 1 2(顺便说明不是1 2 3),因为在子任务运行/完成时无法确定。这可能还取决于您的构建配置(调试/发布)。