[.NET]Thread与Task的区别

前言

在学习Thread和Task之前,首先要理解以下概念:

  • 进程与线程
  • 同步与异步
  • 阻塞与非阻塞

1、进程(process)

当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。

而一个进程又是由多个线程所组成的。

2、线程(thread)

线程是程序中的一个执行流,每个线程都有自己的专有寄存器(栈指针、程序计数器等),但代码区是共享的。

多线程是指程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。

3、同步(sync)

发出一个功能调用时,在没有得到结果之前,该调用就不返回。

4、异步(async)

与同步相对,调用在发出之后,这个调用就直接返回了,所以没有返回结果。当这个调用完成后,一般通过状态、通知和回调来通知调用者。对于异步调用,调用的返回并不受调用者控制。

通知调用者的三种方式:

  • 状态:即监听被调用者的状态(轮询),调用者需要每隔一定时间检查一次,效率会很低。
  • 通知:当被调用者执行完成后,发出通知告知调用者,无需消耗太多性能。
  • 回调:与通知类似,当被调用者执行完成后,会调用调用者提供的回调函数。

5、阻塞(block)

阻塞调用是指调用结果返回(或者收到通知)之前,当前线程会被挂起,即不继续执行后续操作。

简单来说,等前一件做完了才能做下一件事。

6、非阻塞(non-block)

非阻塞调用指在不能立刻得到结果之前,该调用不会阻塞当前线程。

什么是 Thread

.NET Framework 在 System.Threading 下提供线程的相关类。一个线程是一组执行指令。

Thread

什么是 Task

.NET Framework 提供了 Threading.Task 类,允许创建任务和异步运行它们。Task 有Wait、ContinueWith、Cancel等操作,有返回值。

Task

Thread与Task的区别

Thread 类主要用于实现线程的创建以及执行。

Task 类表示以异步方式执行的单个操作。

1、Task 是基于 Thread 的,是比较高层级的封装,Task 最终还是需要 Thread 来执行

2、Task 默认使用后台线程执行,Thread 默认使用前台线程

static void Main(string[] args)
{
    Thread thread = new Thread(obj => { Thread.Sleep(3000); });
    thread.Start();
}

上面代码,主程序在3秒后结束。

static void Main(string[] args)
{
    Task<int> task = new Task<int>(() => 
    {
        Thread,Sleep(3000);
        return 1;
    });
    task.Start();
}

而这段代码,会瞬间结束。

3、Task 可以有返回值,Thread 没有返回值

虽然 Thread 可以通过 Start 方法参数来进行返回值处理,但十分不便。

public void Start (object parameter);
static void Main(string[] args)
{  
    Task task = new Task(LongRunningTask);
    task.Start();
    Console.WriteLine(task.Result);
}
private static int LongRunningTask()
{
    Thread.Sleep(3000);
    return 1;
}

4、Task 可以执行后续操作,Thread 不能执行后续操作

static void Main(string[] args)
{
    Task task = new Task(LongRunningTask);
    task.Start();
    Task childTask = task.ContinueWith(SquareOfNumber);
    Console.WriteLine("Sqaure of number is :"+ childTask.Result);
    Console.WriteLine("The number is :" + task.Result);
}
private static int LongRunningTask()
{
    Thread.Sleep(3000);
    return 2;
}
private static int SquareOfNumber(Task obj)
{
    return obj.Result * obj.Result;
}

5、Task 可取消任务执行,Thread 不行

static void Main(string[] args)
{
    using (var cts = new CancellationTokenSource())
    {
        Task task = new Task(() => { LongRunningTask(cts.Token); });
        task.Start();
        Console.WriteLine("Operation Performing...");
        if(Console.ReadKey().Key == ConsoleKey.C)
        {
            Console.WriteLine("Cancelling..");
            cts.Cancel();
        }                
        Console.Read();
    }
}
private static void LongRunningTask(CancellationToken token)
{
    for (int i = 0; i < 10000000; i++)
    {
        if(token.IsCancellationRequested)
        {
            break;
        }
        else
        {                  
            Console.WriteLine(i);
        }               
    }          
}

6、异常传播

Thread 在父方法上获取不到异常,而 Task 可以。

参考文档

posted @ 2020-10-09 14:01  大杂草  阅读(9535)  评论(3编辑  收藏  举报