代码之家  ›  专栏  ›  技术社区  ›  vico

taskCreationOptions.AttachedToParent不使专利任务等待子项

c#
  •  0
  • vico  · 技术社区  · 5 年前

    根据书 Kort W. - Exam Ref 70-483. Programming in C# 父线程应始终等待子线程,并因此带来:

    0 1 2

    但在大多数情况下我有

    0 0 0

    我希望taskCreationOptions.AttachedToParent将使主线程等待子线程。

    public static void parenThr()
    {
    
        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;
            }
        );
    
        parent.ContinueWith(
            (s) =>
            {
                foreach (var i in s.Result)
                {
                    Console.WriteLine("res {0}",i);
                }
            }
        );
    
    }
    

    为什么主线程不等待子线程完成?

    1 回复  |  直到 5 年前
        1
  •  0
  •   FCin    5 年前

    默认情况下 Task.Run 从开始 TaskCreationOptions.DenyChildAttached .

    MSDN :

    任务创建选项.denychildatatached

    指定任何试图作为附加任务执行的子任务 子任务(即使用AttachedToParent选项创建) 无法附加到父任务,将改为执行 作为独立的子任务。有关更多信息,请参阅附件和 分离的子任务。

    你应该使用 Task.Factory.StartNew ,以便您可以指定自己的参数。

    public static async Task Do()
    {
        Task<int[]> parent = Task.Factory.StartNew
        (
            () =>
            {
                var results = new int[3];
    
                Task.Factory.StartNew(() => results[0] = 0, default(CancellationToken), TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
                Task.Factory.StartNew(() => results[1] = 1, default(CancellationToken), TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
                Task.Factory.StartNew(() => results[2] = 2, default(CancellationToken), TaskCreationOptions.AttachedToParent, TaskScheduler.Default);
    
                return results;
            }
        , default(CancellationToken), TaskCreationOptions.None, TaskScheduler.Default);
    
        var ints = await parent;
    
        foreach (var i in ints)
        {
            Console.WriteLine("res {0}", i);
        }
    }
    

    为了避免潜在的混淆 TaskScheduler 如果使用,则应使用带有taskscheduler参数的重载。