zoukankan      html  css  js  c++  java
  • [.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 可以。

    参考文档

  • 相关阅读:
    C++PRIMER PLUS第六版课后编程答案 5.1-5.5
    C++PRIMER PLUS第六版课后编程答案 4.6-4.10
    C++PRIMER PLUS第六版课后编程答案 4.1-4.5
    C++PRIMER PLUS第六版课后编程题答案 3.1-3.7
    C++ Primer Plus 第六版课后编程答案 2.6-2.7
    C++ Primer Plus 第六版课后编程答案 2.1-2.5
    jmf天昏地暗之路(三)---抓取当前帧照片并保存为bmp格式(结束)
    win7下chm文件无法正常显示所示
    HDOJ 2929 Bigger is Better
    Codeforces Round #202 (Div. 2) A,B
  • 原文地址:https://www.cnblogs.com/liang24/p/13785480.html
Copyright © 2011-2022 走看看