• C# 线程知识--使用Task执行异步操作


    原文地址:http://www.cnblogs.com/pengstone/archive/2012/12/23/2830238.html

    感觉这篇文章不错,copy了一份;

       在C#4.0之前需要执行一个复杂的异步操作时,只能使用CLR线程池技术来执行一个任务。线程池执行异步任务时,不知道任务何时完成,以及任务的在任务完成后不能获取到返回值。但是在C#4.0中引人了一个的任务(System.Threading.Tasks命名空间的类型)机制来解决异步操作完成时间和完成后返回值的问题。

    1.使用Task类创建并执行简单任务

    通过使用Task的构造函数来创建任务,并调用Start方法来启动任务并执行异步操作。创建任务时,必须传递一个Action或Action<Object>类型的委托回调方法,可以选择的传递任务执行时说需要的数据对象等。Task类的构造函数如下:

        public Task(Action action);
            public Task(Action<object> action, object state);
            public Task(Action action, CancellationToken cancellationToken);
            public Task(Action action, TaskCreationOptions creationOptions);
            public Task(Action<object> action, object state, CancellationToken cancellationToken);
            public Task(Action<object> action, object state, TaskCreationOptions creationOptions);
            public Task(Action action, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
            public Task(Action<object> action, object state, CancellationToken cancellationToken, TaskCreationOptions creationOptions);
    

      示例代码:

     
     static void Main(string[] args)
            {
                //先声明一个委托
                Console.WriteLine("主线程执行业务处理---开始.");
                Task task = new Task(() =>
                {
                    Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作----开始.");
                    for (int i = 0; i < 10; i++)
                    {
                        Console.WriteLine(i);
                    }
                    Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作----结束.");
                });
                task.Start();
                Console.WriteLine("主线程执行其他处理---结束");
    
    
                //
                Console.ReadKey(false);
            }
    

      

      

    结果:

    主线程执行业务处理---开始.
    主线程执行其他处理---结束
    使用System.Threading.Tasks.Task执行异步操作----开始.
    0
    1
    2
    3
    4
    5
    6
    7
    8
    9
    使用System.Threading.Tasks.Task执行异步操作----结束.

     2.等待任务的完成并获取返回值

    使用任务执行异步操作时,最主要的是要后的任务完成时的返回值。在任务类中有一个实例方法Wait(有许多重载版本)他能等待任务的完成,我们也可以通过Task类的派生类Task<TResult>创建一个异步任务,并指定任务完成时返回值的类型,这样可以通过Task<TResult>的实例对象获取到任务完成后的返回值。创建一个异步任务并执行0到100求和操作返回最后的计算结果,示例代码:

    Console.WriteLine("主线程执行业务处理---开始.");
                Task<int> task1 = new Task<int>(()=> {
                    Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作----开始.");
                    int sum = 0;
                    for (int i = 0; i < 50; i++)
                    {
                        sum += i;
                    }
                    return sum;
                });
                task1.Start();
                Console.WriteLine("主线程执行其他处理---结束");
                //等待任务的完成执行过程。
                task1.Wait();
                Console.WriteLine("任务执行结果:{0}", task1.Result.ToString());
    

    执行结果:

    主线程执行业务处理---开始.
    主线程执行其他处理---结束
    使用System.Threading.Tasks.Task执行异步操作----开始.
    任务执行结果:1225

     Task类还有一些静态方法,WaitAll用于等待提供的所有 System.Threading.Tasks.Task 对象完成执行过程和Wait用于等待提供的任一个 System.Threading.Tasks.Task 对象完成执行过程,这两个方法都有一些重载版本。

    //等待所有任务完成  
    public static void WaitAll(params Task[] tasks);
    //等待任意一个任务完成
    public static int WaitAny(params Task[] tasks);
    

      3.使用ContinueWith方法在任务完成时启动一个新任务

    在使用能够Task类的Wait方法等待一个任务时或派生类的Result属性获得任务执行结果都有可能阻塞线程,为了解决这个问题可以使用ContinueWith方法,他能在一个任务完成时自动启动一个新的任务来处理执行结果。

    示例代码:

      Console.WriteLine("主线程执行业务处理---开始.");
                Task<int> task2 = new Task<int>(() => {
                    Console.WriteLine("使用System.Threading.Tasks.Task执行异步操作----开始.");
                    int sum = 0;
                    for (int i = 0; i < 50; i++)
                    {
                        sum += i;
                    }
                    return sum;
                });
                task2.Start();
    
                Console.WriteLine("主线程执行其他处理---结束");
                task2.ContinueWith(r=>{
                    Console.WriteLine("任务执行结果:{0}", r.Result.ToString());
     });
    

      

    执行结果:

    主线程执行业务处理---开始.
    主线程执行其他处理---结束
    使用System.Threading.Tasks.Task执行异步操作----开始.
    任务执行结果:1225

     4.创建父子任务和任务工厂的使用

    通过Task类创建的任务是顶级任务,可以通过使用 TaskCreationOptions.AttachedToParent 标识把这些任务与创建他的任务相关联,所有子任务全部完成以后父任务才会结束操作。示例如下:

       public static void ParentChildTask()
            {
                Task<string[]> parent = new Task<string[]>(state =>
                {
                    Console.WriteLine(state);
                    string[] result = new string[2];
                    //创建并启动子任务
                    new Task(() => { result[0] = "我是子任务1。"; }, TaskCreationOptions.AttachedToParent).Start();
                    new Task(() => { result[1] = "我是子任务2。"; }, TaskCreationOptions.AttachedToParent).Start();
                    return result;
                }, "我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行");
                parent.ContinueWith(t =>
                {
                    Array.ForEach(t.Result, r => Console.WriteLine(r));
                });
                //启动父任务
                parent.Start();
            }
    

    结果:

    我是父任务,并在我的处理过程中创建多个子任务,所有子任务完成以后我才会结束执行
    我是子任务1。
    我是子任务2。

  • 相关阅读:
    [转载]「服务」WCF中NetNamedPipeBinding的应用实例
    [转载] ABP框架理论学习之后台工作(Jobs)和后台工作者(Workers)
    .NET Core use NLog
    把.netcore console 安装到Windows 系统服务。
    利用Linq Skip() Take()分页
    C#访问Java的WebService添加SOAPHeader验证的问题
    马丁福勒 关于微服务特点的描述
    转载 springboot 配置读取
    luajit与NYI
    lua启用lua-resty-core
  • 原文地址:https://www.cnblogs.com/alphafly/p/5147843.html
Copyright © 2020-2023  润新知