异步编程之Task

概念

Task是一个管理并行工作单元的轻量对象,相当于ThreadPool。处于命名空间System.Threading.Tasks下。

使用

  • 创建和执行任务

有两种方式创建,一种是调用Task.Run(),另一种是使用Task.Factory.StartNew()
如下示例:

    Task t1 = Task.Run(() =>
    {
        Console.WriteLine("第一个任务");
    });
    Task t2 = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("第二个任务");
    });
  • 等待一个或多个任务完成

无条件等待任务完成:使用Task.Wait()等待一个任务完成,调用改方法会一直阻塞线程,直到该任务完成。

    Task t1 = Task.Run(() =>
    {
        Thread.Sleep(500);
        Console.WriteLine("第一个任务");
    });
    Console.WriteLine($"t1.Status:{t1.Status}");    // t1.Status:WaitingToRun
    t1.Wait();  //无条件等待t1完成
    Console.WriteLine($"t1.Status:{t1.Status}");    // t1.Status:RanToCompletion

有条件等待任务完成:使用Task.Wait(Int32)或者Task.Wait(TimeSpan)阻塞线程,等待任务完成或者时间间隔结束。

    Task t1 = Task.Run(() =>
    {
        Thread.Sleep(500);
        Console.WriteLine("第一个任务");

    });
    Console.WriteLine($"t1.Status:{t1.Status}");    
    t1.Wait(100);
    bool completed = t1.IsCompleted;
    Console.WriteLine($"t1 completed:{completed},t1.Status:{t1.Status}");
    if (!completed)
    {
        Console.WriteLine("t1任务完成前时间已结束");
    }
    //output:
    //t1.Status:WaitingToRun
    //t1 completed:False,t1.Status:Running
    //t1任务完成前时间已结束
  • 取消任务

使用CancelationToken取消令牌可以对Task做取消操作

    static void Main(string[] args)
    {
        CancellationTokenSource cancellationTokenSource = new CancellationTokenSource();
        CancellationToken cancellationToken = cancellationTokenSource.Token;
        Task t1 = Task.Run(() =>
        {
            Thread.Sleep(1000);
            Console.WriteLine("第一个任务");

        });
        Task t2 = Task.Factory.StartNew(() =>
        {
            Thread.Sleep(500);
            RunMethod(cancellationToken);
            Console.WriteLine("第二个任务");
        },cancellationToken);
        //Thread.Sleep(2000)
        cancellationTokenSource.Cancel();
        Task.WaitAll(t1, t2);
    }
    private static void RunMethod(CancellationToken cancellationToken)
    {
        Console.WriteLine("进入 取消任务的测试方法");
        cancellationToken.ThrowIfCancellationRequested();
        Console.WriteLine("结束 取消任务的测试方法");
    }
    //output:
    //    进入 取消任务的测试方法
    //    第一个任务
    //如果Thread.Sleep(2000):
    //    进入 取消任务的测试方法
    //    结束 取消任务的测试方法
    //    第二个任务
    //    第一个任务
  • 异常处理

基本异常处理:

    Task t1 = Task.Run(() =>
    {
        Console.WriteLine("第一个任务");
    });
    Task t2 = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("第二个任务");
    });
    Task t3 = Task.Run(() =>
    {
        throw new DivideByZeroException();
    });
    try
    {
        Task.WaitAll(t1, t2, t3);
    }
    catch (AggregateException ex)
    {
        foreach (var inner in ex.InnerExceptions)
        {
            Console.WriteLine(inner.Message);
        }
    }

使用迭代的异常处理Handler:
当我们需要哪些异常需要处理,哪些异常需要向上传递,System.AggregateException提供了一个Handle()方法来处理AggregateException中的每一个异常,返回true,则表示异常已处理,不用抛出,返回false,抛出异常

    Task t1 = Task.Run(() =>
    {
        Console.WriteLine("第一个任务");
    });
    Task t2 = Task.Factory.StartNew(() =>
    {
        Console.WriteLine("第二个任务");
    });
    Task t3 = Task.Run(() =>
    {
        throw new DivideByZeroException();
    });
    try
    {
        Task.WaitAll(t1, t2, t3);
    }
    catch (AggregateException ex)
    {
        ex.Handle((inner) =>
        {
            if (inner is OperationCanceledException)
            {
                return true;
            }
            else
            {
                return false;
            }
        });
    }

源码:

https://github.com/zhaobingwang/Demo/tree/master/TaskDemo

参考

MSDN:Task
博客园-吾爱易逝:.Net4.0 任务(Task)
.NET 并行(多核)编程系列之五 Task执行和异常处理

猜你喜欢

转载自blog.csdn.net/zhaobw831/article/details/79573291