C#——多线程之Task

这篇具有很好参考价值的文章主要介绍了C#——多线程之Task。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。


前言

在代码编写过程中,经常会用到多线程的知识,实现方法有很多种,突然想总结并理清楚其中的相关性与差异性。故以此开篇总结各种工具的用法与注意事项。本篇将对Task稍作总结。


一、Task是什么?

Task 是 .NET 中用于表示异步操作的类,它提供了一种简单和强大的方式来处理异步编程。Task 可以用于各种应用场景和功能,包括:

  1. 异步执行代码:Task 允许在单独的线程上执行代码块,从而避免阻塞主线程,提高程序的响应性和并发性。
  2. 等待异步操作完成:通过 await 关键字可以等待 Task 完成,从而实现非阻塞的异步操作。
  3. 并行执行多个任务:Task 可以用于并行执行多个独立的任务,从而加快任务的完成速度,提高系统的性能。
  4. 处理异常:Task 提供了异常处理机制,可以在异步操作中捕获和处理异常。
  5. 轻量级的线程管理:Task 使用线程池来管理线程,避免了频繁创建和销毁线程的开销,使得线程的管理更加高效。
  6. 取消异步操作:Task 支持取消操作,可以通过 CancellationToken 来取消正在进行的异步操作。

总的来说,Task 是一种非常有用的工具,它在异步编程中起着至关重要的作用,可以帮助开发人员编写高效、响应式和可靠的异步代码。

二、各应用场景以及实例分析

1.异步执行代码

假设我们需要在后台线程中执行一个耗时的操作,而不阻塞主线程。使用 Task 可以很方便地实现这一点。例如,我们可以使用 Task.Run 方法在后台线程中执行一个计算操作,然后在主线程中继续执行其他代码:

代码如下(示例):

        static void Main(string[] args)
        {
            Task.Run(() =>
            {
                Console.WriteLine("task");
                Task.Delay(2000).Wait(); //模拟耗时操作
                Console.WriteLine("taskEnd");
            });
            Task.Delay(1000).Wait();
            Console.WriteLine($"main");
            Console.ReadKey();
        }

结果如下图:
C#——多线程之Task,# C#基础,c#

2.等待异步操作完成

使用 await 关键字可以等待 Task 完成,从而实现非阻塞的异步操作。例如,在 Windows Forms 或 WPF 应用程序中,我们可以在异步方法中使用 await 来等待异步操作完成后更新 UI:

        public static async Task wait()
        {
            await Task.Delay(2000); //将等待2秒后,继续执行下面的代码
            Console.WriteLine("Wait 2000 ms");
        }

3.并行执行多个任务

假设我们有多个独立的任务,可以使用 Task.WhenAll 方法来等待它们执行完成。
代码如下(示例):

        static async Task test()
        {
            Task[] tasks = new Task[3];
            tasks[0] = wait();
            tasks[1] = wait2();
            tasks[2] = wait3();

            await Task.WhenAll(tasks);

            Console.WriteLine("main");
            Console.ReadKey();

        }
        public static async Task wait()
        {
            await Task.Delay(2000);
            Console.WriteLine("Wait 2000 ms");
        }
        public static async Task wait2()
        {
            await Task.Delay(3000);
            Console.WriteLine("Wait 3000 ms");
        }
        public static async Task wait3()
        {
            await Task.Delay(4000);
            Console.WriteLine("Wait 4000 ms");
        }

结果如下图:
C#——多线程之Task,# C#基础,c#

ps:
上述代码有个小细节:在 test() 方法中,没有显式地调用 Start() 方法,因为在使用 async/await 时不需要手动启动任务。async 方法本身会确保异步方法在调用时会自动启动,所以不需要手动调用 Start()。

遇到点小问题:
我在通过入下代码,new task进行新建,start进行启动时,出现Main在wait 。。前先被打印出来如下:

        static async Task test()
        {
            Task[] tasks = new Task[3]
            {
               new Task( ()=>  wait()),
               new Task( ()=>  wait2()),
               new Task( ()=>  wait3())
            };
            foreach (var item in tasks)
            {
                item.Start();
            }
            await Task.WhenAll(tasks);
            Console.WriteLine("main");
            Console.ReadKey();
        }

C#——多线程之Task,# C#基础,c#

Task.WhenAll() 方法只能等待当前线程池中的任务完成。如果任务没有被调度到线程池上运行,那么 Task.WhenAll() 方法将无法等待这些任务完成。
当你使用 Task.Run() 或 Task.Factory.StartNew() 方法创建任务时,这些任务会被自动调度到线程池上运行,因此 Task.WhenAll() 方法可以等待它们的完成。
而通过 new Task() 创建任务对象后,手动调用 Start() 方法来启动任务,但这些任务并没有被自动调度到线程池上运行。因此,Task.WhenAll() 方法无法等待这些任务完成。

4.处理异常

Task 提供了异常处理机制,可以在异步操作中捕获和处理异常。例如,我们可以使用 try-catch 块来处理异步操作中可能抛出的异常:

        static void Main(string[] args)
        {
            test();
            Console.WriteLine("main");
            Console.ReadKey();
        }

        static async void test()
        {
            try
            {
                await wait();
            }
            catch (Exception)
            {
                Console.WriteLine("报错啦!");
            }
        }


        public static async Task wait()
        {
            await Task.Delay(2000);
            Console.WriteLine("Wait 2000 ms");
            throw new Exception("wwww");
        }

结果如下:
C#——多线程之Task,# C#基础,c#

ps:此处需要注意的是try/catch在await上下文时才能生效,否则无法捕获到异常。

5.取消异步操作

Task 支持取消操作,可以通过 CancellationToken 来取消正在进行的异步操作。例如,我们可以在异步方法中检查 CancellationToken 的状态,并在需要时取消操作:

        static void Main(string[] args)
        {

            CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
            CancellationToken cancellationToken = cancellationTokenSource.Token;

            Task.Run(async () =>
            {
                try
                {
                    int i = 0;
                    while (!cancellationToken.IsCancellationRequested)
                    {
                        await Task.Delay(1000);
                        Console.WriteLine($"第{i}次等待");
                        i += 1;
                    }
                    cancellationToken.ThrowIfCancellationRequested();//可弹出OperationCanceledException类型的错误
                }
                catch (OperationCanceledException)
                {
                    Console.WriteLine($"任务被取消");
                }
            }, cancellationToken);

            Thread.Sleep(5000);
            cancellationTokenSource.Cancel();//取消任务

            Console.ReadKey();
        }

结果如下图:
C#——多线程之Task,# C#基础,c#

ps:其实通过一个全局布尔变量也可以达到上面中止任务的效果,但cancellationToken中封装了一些取消任务后的回调,减少了自己码代码的时间,但增加了学习理解的成本。

三、一些其他问题

1.WhenAll与WhenAny的区别

WhenAll:是要等待所以的任务完成才返回;如上文并行任务章节内容。
WhenAny:只要一个任务完成,就立马结束等待。如下。

        static async Task test()
        {
            Task[] tasks = new Task[3];
            tasks[0] = wait();
            tasks[1] = wait2();
            tasks[2] = wait3();
            
            await Task.WhenAny(tasks);
            Console.WriteLine("main");
            Console.ReadKey();
        }

C#——多线程之Task,# C#基础,c#


总结

上文我们通过各实例内容,粗略了解了Task的各种应用,在使用中还会遇见多种问题,在此无法详尽的列举出来。在以后的过程中,如果遇见问题的话我会陆续更新到这里,希望本文对大家有所帮助。下次我们将继续了解多线程中的Thread。我们下次再见。文章来源地址https://www.toymoban.com/news/detail-613387.html

到了这里,关于C#——多线程之Task的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • C# Task Parallel Library (TPL) 访问线程池

    //在C#中,可以使用Task Parallel Library (TPL)来访问线程池。 //TPL是一个用于并行编程的框架,它提供了一种简单的方式来创建并行任务, //并 自动利用线程池 来执行这些任务。 //下面是一个使用TPL访问线程池的示例: //csharp using System; using System.Threading.Tasks; class Program {     st

    2024年02月08日
    浏览(76)
  • C#学习相关系列之多线程(七)---Task的相关属性用法

    任务是 架构在线程之上 的,任务最终的执行还是要给到线程去执行的。 任务和线程之间不是一对一的关系,任务更像线程池,任务相比线程池有很小的开销和精确的控制。 (总的来说Task的用法更为先进,在多线程的时候应该优先考虑Task) 1. status 当前状态类属性(较多)  C

    2024年02月06日
    浏览(30)
  • Unity C# 之 Task、async和 await 、Thread 基础使用的Task的简单整理

    目录 Unity C# 之 Task、async和 await 、Thread 基础使用的Task的简单整理 一、Task、async和 await 、Thread 基础概念 1、线程,多线程 2、Task  3、async (await ) 二、Task 的基础使用,Task 的创建 和 启动 1、创建并运行一个Task 2、创建有返回值的 Task 3、Task提供了 task.RunSynchronously()用于同步

    2024年02月12日
    浏览(44)
  • C#基础--线程Thread和线程池ThreadPool

    1. 开启一个线程 ThreadStart 是属于System.Threading 中的一个内置委托 ParameterizedThreadStart 是属于System.Threading 中的一个内置委托 2. 暂停/恢复线程 无法实时的去 “暂停 ” 或者 “恢复” 线程,因为线程是由系统调度执行的,而且中间存在一个延时现象,不可能直接帮你执行 3. 终结

    2024年02月16日
    浏览(32)
  • C#基础--进程和线程的认识

    1. 什么是进程? 进程并不是物理的东西,是虚拟出来的,是一种概念。当一个程序开始运行时,它就是一个进程,进程包括运行中的程序和程序所使用到的内存和系统资源。而一个进程又是由多个线程所组成的。是一种计算机概念,是程序在运行的时候,记录当前程序对计算

    2024年02月16日
    浏览(39)
  • Unity C# 之 使用 HttpWebRequest 基础知识/HttpWebRequest 进行异步Post 网络访问/数据流形式获取数据(Task/async/await)的代码简单实现

    目录 Unity C# 之 使用 HttpWebRequest 基础知识/HttpWebRequest 进行异步Post 网络访问/数据流形式获取数据(Task/async/await)的代码简单实现 一、简单介绍 二、实现原理 三、注意事项 四、效果预览 五、关键代码 附录 : HttpWebRequest 的一些基础知识 1、HttpWebRequest 常用属性 2、HttpWebRequest 

    2024年02月05日
    浏览(58)
  • 如何让Task在非线程池线程中执行?

    Task承载的操作需要被调度才能被执行,由于.NET默认采用基于线程池的调度器,所以Task默认在线程池线程中执行。但是有的操作并不适合使用线程池,比如我们在一个ASP.NET Core应用中承载了一些需要长时间执行的后台操作,由于线程池被用来处理HTTP请求,如果这些后台操作也

    2024年02月06日
    浏览(33)
  • c#多线程—基础概念到“双色球”项目实现(附知识点目录、代码、视频)

    总结:视频中对于多线程讲的非常透彻,从线程基础概念—.net不同版本出现的线程方法—多线程常出现问题—双色球项目实践,每个知识点都有代码实操,受益匪浅。附上学习笔记和实操代码。 视频 线程:程序执行的最小单位,任何操作都是由线程完成的,使用同步时,资

    2024年02月11日
    浏览(52)
  • c# Task异步使用

    描述 Task出现之前,微软的多线程处理方式有:Thread→ThreadPool→委托的异步调用,虽然可以满足基本业务场景,但它们在多个线程的等待处理方面、资源占用方面、延续和阻塞方面都显得比较笨拙,在面对复杂的业务场景下,显得有点捉襟见肘 Task是微软在.Net 4.0时代推出来的

    2024年02月11日
    浏览(35)
  • WPF跨线程访问UI对象之Dispatcher的用法(含Task)

    WPF程序员处理多线程的一个方式 - Dispatcher 当我们打开一个WPF应用程序即开启了一个进程,该进程中至少包含两个线程。 一个线程用于处理呈现:隐藏在后台运行 一个线程用于管理用户界面:接收输入、处理事件、绘制屏幕以及运行应用程序代码。即UI线程。 在UI线程中有一

    2024年02月16日
    浏览(38)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包