Skip to content

C# 多线程 04-使用任务平行库 03-组合任务

🏷️ 《C# 多线程》

组合任务

csharp
/// <summary>
/// 组合任务
/// </summary>
/// <param name="args"></param>
static void Main(string[] args)
{
    var firstTask = new Task<int>(() => TaskMethod("First Task", 3));
    var secondTask = new Task<int>(() => TaskMethod("Second Task", 2));

    // 设置后续操作
    firstTask.ContinueWith(t => Console.WriteLine($"The first answer is {t.Result}. " +
        $"Thread id {Thread.CurrentThread.ManagedThreadId}, " +
        $"is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}"),
        TaskContinuationOptions.OnlyOnRanToCompletion);

    firstTask.Start();
    secondTask.Start();

    // 等待上面的两个任务完成
    Thread.Sleep(TimeSpan.FromSeconds(4));

    // 给第二个任务设置后续操作,并使用 TaskContinuationOptions.ExecuteSynchronously 选项尝试同步执行该后续操作
    Task continuation = secondTask.ContinueWith(t => Console.WriteLine($"The first answer is {t.Result}. " +
        $"Thread id {Thread.CurrentThread.ManagedThreadId}, " +
        $"is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}"),
        TaskContinuationOptions.OnlyOnRanToCompletion | TaskContinuationOptions.ExecuteSynchronously);
    // 为上面的后续操作再定义一个后续操作
    continuation.GetAwaiter().OnCompleted(() => Console.WriteLine($"Continuation Task Completed! " +
        $"Thread id: {Thread.CurrentThread.ManagedThreadId}, " +
        $"is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}"));

    Thread.Sleep(TimeSpan.FromSeconds(2));
    Console.WriteLine();

    firstTask = new Task<int>(() =>
    {
        // 使用 TaskCreationOptions.AttachedToParent 运行子任务
        // 只有所有子任务结束工作,父任务才会完成
        var innerTask = Task.Factory.StartNew(() => TaskMethod("Second Task", 5), TaskCreationOptions.AttachedToParent);

        innerTask.ContinueWith(t => TaskMethod("Third Task", 2), TaskContinuationOptions.AttachedToParent);

        return TaskMethod("First task", 2);
    });

    firstTask.Start();

    // 打印任务状态
    // firstTask 父任务处理仍在执行中时状态为 running
    // 父任务执行结束而子任务仍在执行时状态为 WaitingForChildrenToComplete
    // 全部完成后状态为 RanToCompletion
    while (!firstTask.IsCompleted)
    {
        Console.WriteLine(firstTask.Status); // running / WaitingForChildrenToComplete
        Thread.Sleep(TimeSpan.FromSeconds(0.5));
    }
    Console.WriteLine(firstTask.Status); // RanToCompletion
    Thread.Sleep(TimeSpan.FromSeconds(10));

    Console.ReadLine();
}

static int TaskMethod(string name, int seconds)
{
    Console.WriteLine($"Task {name} is running on a thread id {Thread.CurrentThread.ManagedThreadId}. " +
        $"Is thread pool thread: {Thread.CurrentThread.IsThreadPoolThread}");
    Thread.Sleep(TimeSpan.FromSeconds(seconds));
    return 42 * seconds;
}

打印结果

txt
Task First Task is running on a thread id 3. Is thread pool thread: True
Task Second Task is running on a thread id 4. Is thread pool thread: True
The first answer is 126. Thread id 3, is thread pool thread: True
The first answer is 84. Thread id 1, is thread pool thread: False
Continuation Task Completed! Thread id: 5, is thread pool thread: True

Running
Task Second Task is running on a thread id 4. Is thread pool thread: True
Task First task is running on a thread id 6. Is thread pool thread: True
Running
Running
Running
Running
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
Task Third Task is running on a thread id 5. Is thread pool thread: True
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
WaitingForChildrenToComplete
RanToCompletion