C# Task使用方法
发布网友
发布时间:2024-09-27 09:17
我来回答
共1个回答
热心网友
时间:2024-10-20 13:11
在C#中,任务(Task)是线程的进一步抽象,使用任务可以简化线程的管理,绕过一些琐事。首先,我们从创建线程开始。创建线程非常简单,可以新建一个Thread类,传入一个ThreadStart委托(无参数返回void),然后调用Start方法。然而,线程在执行完委托后就结束了,因此需要一种方法在创建的线程中继续执行代码。一种实现方式是构建一个委托的栈(也可以使用队列、链表等),在创建的线程中轮询栈中是否有未完成的委托,若有则取出并执行委托。只要向栈中添加委托,它们就会在创建的线程中运行。
接下来是任务(Task)的介绍。任务是对前面操作的封装,包含了要运行的委托以及将委托放入线程运行的封装。任务通常被放置在线程池中运行,并且是后台线程。主线程结束时,并不会管后台线程是否运行,因此调用thread.sleep方法让后台线程有时间完成任务。
然后是async/await关键字,它们表示什么?其实很简单,前面我们调用了task.Start,但并不知道任务何时结束。我们可以调用回调函数表示任务完成,而async/await则简化了这一过程,await相当于在任务结束后调用回调的过程,避免了回调的麻烦。值得注意的是,在await任务结束后,依然在线程池中运行,与回调情形一致,这也是await可以避免线程阻塞的原因。
在实现任务时,有时任务可能包含其他任务。任务有几种类型,包括未开始的任务、混合任务、使用async关键字的任务等。未开始的任务不符合规范,通常需要调用Start或者直接使用await。混合任务可能在调用线程中运行部分代码,而返回一个运行中的任务。async关键字的任务在使用时,编译器会提示使用await关键字,因为它们使用了await开启了任务,使得方法内部await之后的语句不一定在该方法开始时的线程范围内,因此需要在方法外部使用await关键字。
任务的开启方法主要有Task.Run和TaskFactory.StartNew。Task.Run实际上是TaskFactory.StartNew的封装,对返回的task进行进一步处理,返回一个单独的task,不需要手动await。
对于任务的其他方法,如Task.Wait()、Task.RunSynchronously、Task.ContinueWith、Task.WhenAny和Task.WhenAll,分别用于等待任务完成、在当前线程运行任务、在任务完成时执行后续操作、等待任意任务完成和等待所有任务完成。
任务的取消机制对于长时间任务尤为重要,可以使用CancellationTokenSource。取消任务的机制是轮询是否被取消,但不是即时的,也不适用于单个长时间操作。传递token而不是本身的原因是为了控制取消机制的封装,遵循设计原则。
在捕获异常时,无论在哪种线程抛出异常,都会在该线程中捕获。后台线程的异常不会导致程序停止运行,但异常捕获的具体方法可能需要特定配置,这里暂时忘记了具体步骤,日后会再查找。