TaskFactory.StartNew(action,creationOptions)

Taskは入れ子にする事も出来る。

MainClass.csにて、

// 名前空間の登録
using System;   // 共通データ型と基本クラス(System名前空間)
using System.Threading;
using System.Threading.Tasks; // マルチスレッド(System.Threading名前空間)

// MainClassの定義
class MainClass
{

    // Mainメソッドの定義
    static void Main()
    {

        // 親タスクの実行
        var pt = Task.Factory.StartNew(() => // Task.Factory.StartNew(action)で実行.
        {

            // 親タスクの開始
            Console.WriteLine("ParentTask Begin");  // "ParentTask Begin"と出力.

            // 子タスクの実行
            var ct = Task.Factory.StartNew(() => // Task.Factory.StartNew(action)で実行.
            {

                // 子タスクの開始
                Console.WriteLine("ChildTask Begin");  // "ChildTask Begin"と出力.

                // 5秒休止
                Thread.Sleep(5000); // Thread.Sleepで5000ミリ秒休止.

                // 子タスクの終了
                Console.WriteLine("ChildTask End");    // "ChildTask End"と出力.

            });

            // 3秒休止
            Thread.Sleep(3000); // Thread.Sleepで3000ミリ秒休止.

            // 親タスクの終了
            Console.WriteLine("ParentTask End");    // "ParentTask End"と出力.

        });

        // 完了まで待つ.
        pt.Wait();   // Task.Waitで待つ.

        // 終了
        Console.WriteLine("All End");   // "All End"と出力.

    }

}

このように書いて実行しても、

外側のタスクが早く終了してしまうので、内側のタスクの"ChildTask End"まで到達しない。
外側のタスクが早く終了してしまうので、内側のタスクの"ChildTask End"まで到達しない。

外側のタスクが早く終了してしまうので、内側のタスクの"ChildTask End"まで到達しない。
そこでタスクに親子関係を作るため、第2引数にTaskCreationOptions.AttachedToParentを指定する。

TaskFactory.StartNew メソッド (System.Threading.Tasks) | Microsoft Docs
[雑記] スレッド プールとタスク - C# によるプログラミング入門 | ++C++; // 未確認飛行 C
C# 非同期、覚え書き。 - Qiita

MainClass.csを

こうすると、

"ChildTask End"が出ている。
"ChildTask End"が出ている。

"ChildTask End"が出ている。
"ParentTask End"が先に出ているが、これはここの出力が先に実行されるからで、この親タスクが終わった後に、子タスクが終わるまで待って、子タスクが終わったら、一緒に親タスクの外に出ていって"All End"のところに到達する。

Sample/dotnet/TaskFactory/StartNew_action_creationOptions/src/TaskFactory_ at master · bg1bgst333/Sample · GitHub