C# Task

一、主线程阻塞

1、阻塞等待所有线程执行结束,再执行下面的操作

语法:Task.WaitAll(task数组);

2、阻塞等待任一线程执行结束,再执行下面的操作

语法:Task.WaitAny(task数组);

3、案例

private void btnTask_Click(object sender, EventArgs e)
{
    Console.WriteLine("开始执行");

    List<Task> tasks = new List<Task>();
    tasks.Add(Task.Run(() => { this.Print("小新", "1"); }));
    tasks.Add(Task.Run(() => { this.Print("小白", "2"); }));
    tasks.Add(Task.Run(() => { this.Print("小葵", "3"); }));
    tasks.Add(Task.Run(() => { this.Print("阿呆", "4"); }));
    // 阻塞,直到任一线程执行完毕
    Task.WaitAny(tasks.ToArray());
    Console.WriteLine("有一位小朋友到了,准备游戏");
    // 集合转化成数组,阻塞直到线程执行完毕
    Task.WaitAll(tasks.ToArray());
    Console.WriteLine("所有小朋友到了,开始玩扮家家酒");
    Console.WriteLine("结束执行");
}

private void Print(string name, object project) {
    Console.WriteLine($"开启线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
    Thread.Sleep(1000*2);
    Console.WriteLine($"结束线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
}

缺点:阻塞主线程,窗口没法移动

二、TaskFactory

1、创建一个延续任务,当所有线程(数组)执行完毕后执行延续任务

语法:

TaskFactory taskFactory = new TaskFactory()

taskFactory.ContinueWhenAll(线程数组,延续任务)

2、创建一个延续任务,当任一线程(数组)执行完毕后执行延续任务

语法:

TaskFactory taskFactory = new TaskFactory();

taskFactory.ContinueWhenAny(task数组, 后续任务);

优点:线程列表的后续任务受控,与主线程异步不影响窗口

缺点:无法在主线程中执行,所有线程执行完后,再执行的任务,需要和WaitAll()一起使用,taskFactoy也是一个task

3、案例

private void btnTask_Click(object sender, EventArgs e)
{
    Console.WriteLine("开始执行");

    List<Task> tasks = new List<Task>();
    tasks.Add(Task.Run(() => { this.Print("小新", "1"); }));
    tasks.Add(Task.Run(() => { this.Print("小白", "2"); }));
    tasks.Add(Task.Run(() => { this.Print("小葵", "3"); }));
    tasks.Add(Task.Run(() => { this.Print("阿呆", "4"); }));

    TaskFactory taskFactory = new TaskFactory();

    // 创建一个延续任务,当线程数组任一线程执行完毕后,执行这个延续任务
    taskFactory.ContinueWhenAny(tasks.ToArray(), (_) => {
        Console.WriteLine($"有一个小朋友到了,开始选择游戏,线程-{Thread.CurrentThread.ManagedThreadId}");
    });

    // 创建一个延续任务,等待所有线程结束后执行
    taskFactory.ContinueWhenAll(tasks.ToArray(), (_) => {
        Console.WriteLine($"所有小朋友都到了,开始进行游戏。线程-{Thread.CurrentThread.ManagedThreadId}");
    });
    // 与子线程异步
    Console.WriteLine("执行结束");
}

private void Print(string name, object project) {
    Console.WriteLine($"开启线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
    Thread.Sleep(1000*2);
    Console.WriteLine($"结束线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
}

4、与WaitAll()一起使用

private void btnTask_Click(object sender, EventArgs e)
{
    Console.WriteLine("开始执行");

    List<Task> tasks = new List<Task>();
    tasks.Add(Task.Run(() => { this.Print("小新", "1"); }));
    tasks.Add(Task.Run(() => { this.Print("小白", "2"); }));
    tasks.Add(Task.Run(() => { this.Print("小葵", "3"); }));
    tasks.Add(Task.Run(() => { this.Print("阿呆", "4"); }));

    TaskFactory taskFactory = new TaskFactory();

    // 创建一个延续任务,当线程数组任一线程执行完毕后,执行这个延续任务
    taskFactory.ContinueWhenAny(tasks.ToArray(), (_) => {
        Console.WriteLine($"有一个小朋友到了,开始选择游戏,线程-{Thread.CurrentThread.ManagedThreadId}");
    });

    // 创建一个延续任务,等待所有线程结束后执行
    tasks.Add(taskFactory.ContinueWhenAll(tasks.ToArray(), (_) => {
        Console.WriteLine($"所有小朋友都到了,开始进行游戏。线程-{Thread.CurrentThread.ManagedThreadId}");
    }));
    // taskFactory也是一个task
    Task.WaitAll(tasks.ToArray());
    // 与子线程异步
    Console.WriteLine("执行结束");
}

private void Print(string name, object project) {
    Console.WriteLine($"开启线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
    Thread.Sleep(1000*2);
    Console.WriteLine($"结束线程-线程名字:{Thread.CurrentThread.ManagedThreadId.ToString("00")}-用户名:{name}-项目名:{project}");
}

 

posted @ 2025-06-29 18:19  市丸银  阅读(26)  评论(0)    收藏  举报