第26章 计算限制的异步操作(4)

本文探讨了在C#中利用任务(task)概念处理异步、受计算限制的操作,包括如何等待任务完成、获取结果以及处理异常。重点介绍了Task类的静态方法WaitAll和WaitAny,用于等待多个任务的完成。此外,文章还强调了在垃圾回收时通过Task的Finalize方法检查未处理的异常的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

26.5 任务

调用ThreadPool的QueueUserWorkItem方法发起一次异步的、受计算限制的操作时非常简单的。然而,这个技术存在很多限制。最大的问题是没有一个内建的机制让你知道操作在什么时候完成,也没有一个机制在操作完成时获得一个返回值。为了克服这些限制(并解决其他一些问题),Microsoft引入了任务(task)的概念。我们通过System.Threading.Tasks命名空间中的类型来使用它们。

26.5.1 等待任务完成并获取它的结果

using System;
using System.Threading;
using System.Threading.Tasks;

namespace ThreadStudy
{
    class Program
    {
        static void Main(string[] args)
        {
            //创建一个Task
            Task<int> t = new Task<int>(n => Sum(100),CancellationToken.None);
            //可以以后再启动任务
            t.Start();
            //可以显式地等待任务完成
            t.Wait();
            //可以获得结果(Result属性内部会调用Wait)
            Console.WriteLine("The sum is:" + t.Result);
        }

        static int Sum(int num)
        {
            Thread.Sleep(100);
            if (num == 0)
                return 0;
            else
                return num + Sum(num - 1);
        }
    }
}
The sum is:5050
Press any key to continue . . .

如果计算限制的任务抛出一个未处理的异常,这个异常会被“侵吞”并存储到一个集合中,而线程池线程允许返回到线程池中。调用Wait方法或者Result属性时,这些成员会抛出一个System.AggregateException对象

一个线程调用Wait方法时,系统会检查线程要等待的Task是否已开始执行。如果是,调用Wait的线程会阻塞,直到Task运行结束为止。但是,如果Task还没有开始执行,系统可能(取决于TaskScheduler)使用调用Wait的线程来执行Task。如果发生这种情况,那么调用Wait的线程不会阻塞;它会执行Task并立即返回。

AggregateException类型用于封闭异常对象的一个集合。

除了等待单个任务,Task类还提供了两个静态方法,它们允许线程等待一个Task对象数组。其中,Task的静态WaitAny方法会阻塞调用线程,直到数组中的任何一个Task对象完成。这个方法返回一个Int32数组索引值,指明完成的是哪一个Task对象。方法返回后,线程被唤醒并继续执行。如果发生超时,方法返回-1.如果WaitAny通过一个CancellationToken取消,会抛出一个OperationCanceledException。

类似地,Task类还有一个静态WaitAll方法,它阻塞调用线程,直到数组中的所有Task对象都完成。如果所有Task对象都完成,WaitAll方法返回true。如果发生超时,则返回false。如果WaitAll通过CancellationToken而取消,会抛出一个OperationCanceledException。

假如一直不调用Wait或Result,或者一直不查询Task的Exception属性,你的代码就永远注意不到这个异常的发生。这当然不好,因为程序遇到一个未料到的问题,而你竟然没有注意到。所以,当Task对象在垃圾回收时,它的Finalize方法会检查Task是否遇到了一个没有被注意到的异常;如果是,Task的Finalize方法就抛出AggregateException。由于不能捕捉由CLR的终结器方法抛出的异常,所以进程会立即终止。必须调用前面提到的某个成员,确保代码注意到异常并从异常中恢复。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值