C#中Task任务类用法详解

 更新时间:2024年11月12日 10:37:17   作者:辜月廿七  
这篇文章主要为大家详细介绍了C#中Task任务类用法的相关知识,文中的示例代码讲解详细,感兴趣的小伙伴可以跟随小编一起学习一下

前言

Task类是.NET平台上进行多线程和异步操作的重要工具。它提供了简洁而强大的API支持,使得开发者能够更加高效地利用系统资源,实现复杂的并行和异步操作。无论是在I/O密集型操作还是CPU密集型任务中,Task类都能为开发者提供有力的支持。

认识Task

命名空间:System.Threading.Tasks

类名:Task

Task顾名思义就是任务的意思

Task是在线程池基础上进行的改进,它拥有线程池的优点,同时解决了使用线程池不易控制的弊端。

它是基于线程池的优点对线程的封装,可以让我们更方便高效的进行多线程开发。

简单理解:

Task的本质是对线程Thread的封装,它的创建遵循线程池的优点,并且可以更方便的让我们控制线程。

一个Task对象就是一个线程。

创建无返回值Task的三种方式

第一种方式

通过new一个Task对象传入委托函数并启动

        Task t1 = new Task(() =>
        {
            int i = 0;
            while (isRuning)
            {
                print("方式一:" + i);
                ++i;
                Thread.Sleep(1000);
            }
        });
        t1.Start();

第二种方式

通过Task中的Run静态方法传入委托函数

        Task t2 = Task.Run(() =>
        {
            int i = 0;
            while (isRuning)
            {
                print("方式二:" + i);
                ++i;
                Thread.Sleep(1000);
            }
        });

第三种方式

通过Task.Factory中的StartNew静态方法传入委托函数

Task t3 = Task.Factory.StartNew(() =>
{
    int i = 0;
    while (isRuning)
    {
        print("方式三:" + i);
        ++i;
        Thread.Sleep(1000);
    }
});

返回有返回值的Task

第一种方式

通过new一个Task对象闯入委托函数并启动

t1 = new Task<int>(() =>
{
    int i = 0;
    while (isRuning)
    {
        print("方式一:" + i);
        ++i;
        Thread.Sleep(1000);
    }
    return 1;
});
t1.Start();

第二种方式

通过Task中的Run静态方法传入委托函数

t2 = Task.Run<string>(() =>
{
    int i = 0;
    while (isRuning)
    {
        print("方式二:" + i);
        ++i;
        Thread.Sleep(1000);
    }
    return "1231";
});

第三种方式

通过Task.Factory中的StartNew静态方法传入委托函数

t3 = Task.Factory.StartNew<float>(() =>
{
    int i = 0;
    while (isRuning)
    {
        print("方式三:" + i);
        ++i;
        Thread.Sleep(1000);
    }
    return 4.5f;
});

获取返回值

注意:

Resut获取结果时会阻塞线程

即如果task没有执行完成

会等待task执行完成获取到Result

然后再执行后边的代码,也就是说 执行到这句代码时 由于我们的Task中是死循环 

所以主线程就会被卡死

同步执行Task

之前我们举的例子都是通过多线程异步执行的

如果希望Task能够同步执行

只需要调用Task对象中的RunSynchronously方法

注意:需要使用 new Task对象的方式,因为Run和StartNew在创建时就会启动

        Task t = new Task(() =>
        {
            Thread.Sleep(1000);
            print("这是一段话");
        });
        //t.Start();
        t.RunSynchronously();
        print("主线程执行");

不Start 而是 RunSynchronously

Task中线程阻塞的方式

1.Wait方法:等待任务执行完毕,再执行后面的内容

 Task t1 = Task.Run(() =>
 {
     for (int i = 0; i < 5; i++)
     {
         print("t1:" + i);
     }
 });

 Task t2 = Task.Run(() =>
 {
     for (int i = 0; i < 20; i++)
     {
         print("t2:" + i);
     }
 });
​​​​​​​//t2.Wait();

2.WaitAny静态方法:传入任务中任意一个任务结束就继续执行

Task.WaitAny(t1, t2);

3.WaitAll静态方法:任务列表中所有任务执行结束就继续执行

Task.WaitAll(t1, t2);

Task完成后继续其它Task(任务延续)

 1.WhenAll静态方法 + ContinueWith方法:传入任务完毕后再执行某任务

using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
 
public class Test : MonoBehaviour
{
    Task t1,t2;
 
    bool isRuning =true;
    void Start()
    {
        Task.WhenAll(t1, t2).ContinueWith((t) =>
        {
            print("一个新的任务开始了");
            int i = 0;
            while (isRuning)
            {
                print(i);
                ++i;
                Thread.Sleep(1000);
            }
        });
 
        Task.Factory.ContinueWhenAll(new Task[] { t1, t2 }, (t) =>
        {
            print("一个新的任务开始了");
            int i = 0;
            while (isRuning)
            {
                print(i);
                ++i;
                Thread.Sleep(1000);
            }
        });
 
    }
    private void OnDestroy()
    {
        isRuning = false;
    }
}

2.WhenAny静态方法 + ContinueWith方法:传入任务只要有一个执行完毕后再执行某任务 

using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
 
public class Test : MonoBehaviour
{
    Task t1,t2;
 
    bool isRuning =true;
    void Start()
    {
        Task.WhenAny(t1, t2).ContinueWith((t) =>
        {
            print("一个新的任务开始了");
            int i = 0;
            while (isRuning)
            {
                print(i);
                ++i;
                Thread.Sleep(1000);
            }
        });
 
        Task.Factory.ContinueWhenAny(new Task[] { t1, t2 }, (t) =>
        {
            print("一个新的任务开始了");
            int i = 0;
            while (isRuning)
            {
                print(i);
                ++i;
                Thread.Sleep(1000);
            }
        });
 
    }
    private void OnDestroy()
    {
        isRuning = false;
    }
}

取消Task执行

方法一:通过加入bool标识 控制线程内死循环的结束

方法二:通过CancellationTokenSource取消标识源类 来控制

CancellationTokenSource对象可以达到延迟取消、取消回调等功能

using System.Threading;
using System.Threading.Tasks;
using UnityEngine;
 
public class Test : MonoBehaviour
{
    Task t1,t2;
 
    CancellationTokenSource c;
    void Start()
    {
        c = new CancellationTokenSource();
        //延迟取消
        c.CancelAfter(5000);
        //取消回调
        c.Token.Register(() =>
        {
            print("任务取消了");
        });
        Task.Run(() =>
        {
            int i = 0;
            while (!c.IsCancellationRequested)
            {
                print("计时:" + i);
                ++i;
                Thread.Sleep(1000);
            }
        });
 
    }
    private void OnDestroy()
    {
        c.Cancel();
    }
}

总结

1.Task类是基于Thread的封装

2.Task类可以有返回值,Thread没有返回值

3.Task类可以执行后续操作,Thread没有这个功能

4.Task可以更加方便的取消任务,Thread相对更加单一

5.Task具备ThreadPool线程池的优点,更节约性能

到此这篇关于C#中Task任务类用法详解的文章就介绍到这了,更多相关C# Task任务类内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C#中使用WinRAR实现加密压缩及解压缩文件

    C#中使用WinRAR实现加密压缩及解压缩文件

    这篇文章主要介绍了C#中使用WinRAR实现加密压缩及解压缩文件,本文直接给出实例代码,代码中包含详细注释,需要的朋友可以参考下
    2015-07-07
  • C#封装将函数封装为接口dll的简单步骤指南

    C#封装将函数封装为接口dll的简单步骤指南

    在C#中,封装函数为接口并打包成DLL是实现代码重用和模块化的常见方法,此过程包括创建类库项目、定义接口、实现接口、编译项目生成DLL文件,这种方法适用于需要在多个项目间共享功能时使用,需要的朋友可以参考下
    2024-11-11
  • unity实现弧形移动 可角度自定

    unity实现弧形移动 可角度自定

    这篇文章主要为大家详细介绍了unity实现弧形移动,可角度自定,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-06-06
  • 通过C#实现自动售货机接口

    通过C#实现自动售货机接口

    这篇文章主要介绍了通过C#实现自动售货机接口,需要的朋友可以参考下
    2015-07-07
  • C#中科学绘图库ScottPlot的使用详解

    C#中科学绘图库ScottPlot的使用详解

    ScottPlot是基于.Net的一款开源免费的交互式可视化库,支持Winform和WPF等UI框架,本文给大家介绍了C#中科学绘图库ScottPlot的使用方法,文中示例在WPF环境中运行,需要的朋友可以参考下
    2023-12-12
  • c#生成站点地图(SiteMapPath)文件示例程序

    c#生成站点地图(SiteMapPath)文件示例程序

    这篇文章主要介绍了c#生成站点地图(SiteMapPath)文件的示例,大家参考使用
    2013-11-11
  • C#百万数据查询出现超时问题的解决方法

    C#百万数据查询出现超时问题的解决方法

    这篇文章主要介绍了C#百万数据查询出现超时问题的解决方法,是非常实用的技巧,需要的朋友可以参考下
    2014-09-09
  • C#使用listView增删操作实例

    C#使用listView增删操作实例

    这篇文章主要介绍了C#使用listView增删操作的实现方法,实例分析了C#中使用listView控件进行动态添加、选中删除等操作的技巧,具有一定的参考借鉴价值,需要的朋友可以参考下
    2014-12-12
  • 精简高效的C#网站优化经验技巧总结

    精简高效的C#网站优化经验技巧总结

    这篇文章主要为大家介绍了精简高效的C#网站优化经验技巧,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-04-04
  • C#串口编程System.IO.Ports.SerialPort类

    C#串口编程System.IO.Ports.SerialPort类

    这篇文章介绍了C#串口编程System.IO.Ports.SerialPort类,文中通过示例代码介绍的非常详细。对大家的学习或工作具有一定的参考借鉴价值,需要的朋友可以参考下
    2022-06-06

最新评论