C#中的异步多线程4 取消异步、异常处理

一、取消异步执行

可以在异步方法中允许请求终止执行。

    class MyClass
    {
        public async Task RunAsync(CancellationToken ct)
        {
            if (ct.IsCancellationRequested)
                return;
            await Task.Run(() => CycleMethod(ct), ct);
        }
        void CycleMethod(CancellationToken ct)
        {
            Console.WriteLine("Starting CycleMethod");
            const int max = 5;
            for(int i=0;i<max;i++)
            {
                if (ct.IsCancellationRequested)
                    return;
                Thread.Sleep(1000);
                Console.WriteLine("{0} of {1} iterations completed", i + 1, max);
            }
        }
    }
    class Program
    {
        static void Main(string[] args)
        {
            CancellationTokenSource cts = new CancellationTokenSource();
            CancellationToken ct = cts.Token;
            MyClass mc = new MyClass();
            Task t = mc.RunAsync(ct);
            //Thread.Sleep(3000);
            //cts.Cancel();
            t.Wait();
            Console.WriteLine("was cancelled:{0}", ct.IsCancellationRequested);
            Console.ReadLine();
        }
    }

如果注释掉Main中2句,输出如下:

Starting CycleMethod
1 of 5 iterations completed
2 of 5 iterations completed
3 of 5 iterations completed
4 of 5 iterations completed
5 of 5 iterations completed
was cancelled:False

如果不注释,则为:

Starting CycleMethod
1 of 5 iterations completed
2 of 5 iterations completed
3 of 5 iterations completed
was cancelled:True

CancellationToken和CancellationTokenSource被设计用来实现请求终止执行。

1、CancellationToken对象包含一个任务是否应该被取消的信息,拥有CancellationToken对象的任务需要定期检查其token状态。如果CancellationToken对象的IsCancellationRequested属性为true,则任务需停止执行其操作并返回。CancellationToken是不可逆的,并且只能使用一次,一旦IsCancellationRequested属性被设置为true,就不能更改。

2、CancellationTokenSource对象创建可分配给不同任务的CancellationToken对象。任何持有CancellationTokenSource的对象都可以调用其Cancel方法,这回将IsCancellationRequested设置为true。

 

二、异常处理

        static async Task BadAsync()
        {
            try
            {
                await Task.Run(() => { throw new Exception(); });
            }
            catch
            {
                Console.WriteLine("exception in async method");
            }
        }
        static void Main(string[] args)
        {
            Task t = BadAsync();
            t.Wait();
            Console.WriteLine("Task Status:{0}", t.Status);
            Console.WriteLine("Task IsFaulted:{0}", t.IsFaulted);
        }

尽管可以使用try catch抛出exception,但最后Task的状态仍然为RanToCompletion,原因是Task没有被取消,也没有未处理的异常。

posted @ 2020-05-22 16:25  NicolasLiaoRan  阅读(448)  评论(0编辑  收藏  举报