zoukankan      html  css  js  c++  java
  • C# Task TaskFactory 异步线程/异步任务

    Task是.NetFramework3.0出现的,线程是基于线程池,然后提供了丰富的API

    TaskFactory  提供对创建和计划 Task 对象的支持

    创建和启动异步任务

    1、Task task = new Task(() => ThreadPoolHelper.DoSomeThing());
          task.Start();

    2、Task task = Task.Run(() => ThreadPoolHelper.DoSomeThing());

    3、TaskFactory taskFactory = Task.Factory;

          Task task = taskFactory.StartNew(() => ThreadPoolHelper.DoSomeThing());

    Task的线程是源于线程池 ,假如说我想控制下Task的并发数量,该怎么做?

     1             {
     2                 //ThreadPool.SetMaxThreads(8, 8);
     3                 //线程池是单例的,全局唯一的
     4                 //设置后,同时并发的Task只有8个;而且线程是复用的;
     5                 //全局的,请不要这样设置!!!
     6                 for (int i = 0; i < 100; i++)
     7                 {
     8                     int k = i;
     9                     Task.Run(() =>
    10                     {
    11                         Console.WriteLine($"This is k={k},i={i} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    12                         Thread.Sleep(2000);
    13                     });
    14                 }
    15             }
    View Code

    运行上面的代码我们发现几个需要注意的地方:

    1、i的值等于100,因为异步线程的启动并不阻塞主线程;

    2、使用ThreadPool.SetMaxThreads 方法 设置后,虽然能达到效果,但是线程池是单例的,全局唯一的,这样设置会影响整个程序;

    那么如何实现?

     1             {
     2                 List<Task> taskList = new List<Task>();
     3                 for (int i = 0; i < 10000; i++)
     4                 {
     5                     int k = i;
     6                     if (taskList.Count(t => t.Status != TaskStatus.RanToCompletion) >= 20)
     7                     {
     8                         Task.WaitAny(taskList.ToArray());
     9                         taskList = taskList.Where(t => t.Status != TaskStatus.RanToCompletion).ToList();
    10                     }
    11                     taskList.Add(Task.Run(() =>
    12                     {
    13                         Console.WriteLine($"This is {k} running ThreadId={Thread.CurrentThread.ManagedThreadId.ToString("00")}");
    14                         Thread.Sleep(2000);
    15                     }));
    16                 }
    17             }
    View Code

    使用Parallel也可以实现

    Task常用方法

    1、Delay(Int32)、Delay(Int32, CancellationToken)、Delay(TimeSpan)、Delay(TimeSpan, CancellationToken)

    在指定的时间后执行任务

    1             {
    2                 Stopwatch stopwatch = new Stopwatch();
    3                 stopwatch.Start();
    4                 Console.WriteLine("在Delay之前");
    5                 Task.Delay(2000).ContinueWith(t => { Console.WriteLine($"Delay耗时ContinueWith Start{stopwatch.ElapsedMilliseconds}"); ThreadPoolHelper.DoSomeThing(); Console.WriteLine($"Delay耗时ContinueWith End{stopwatch.ElapsedMilliseconds}"); });
    6                 Console.WriteLine($"Delay耗时{stopwatch.ElapsedMilliseconds}");
    7             }
    View Code

    2、ContinueWith(Action<Task,Object>, Object)、ContinueWith(Action<Task>)、ContinueWith<TResult>(Func<Task,Object,TResult>, Object, CancellationToken, TaskContinuationOptions, TaskScheduler)、...

    目标任务完成后异步执行一个延续任务

    3、Wait()、Wait(CancellationToken)、Wait(Int32)、Wait(Int32, CancellationToken)、Wait(TimeSpan)

    等待任务或经过指定时间为止  与Thread.Join方法、waitHandle.WaitOne方法 作用相当

    4、WaitAll(Task[])、WaitAll(Task[], CancellationToken)、WaitAll(Task[], Int32)、WaitAll(Task[], Int32, CancellationToken)、WaitAll(Task[], TimeSpan)

    等待所有任务对象完成执行或经过指定时间为止,或等到取消等待

    5、WaitAny(Task[])、WaitAny(Task[], CancellationToken)、WaitAny(Task[], Int32)、WaitAny(Task[], Int32, CancellationToken)、WaitAny(Task[], TimeSpan)

    等待所有任务对象任何一个任务对象完成执行或经过指定时间为止,或等到取消标记取消

    6、WhenAll(IEnumerable<Task>)、WhenAll(Task[])、WhenAll<TResult>(IEnumerable<Task<TResult>>)、WhenAll<TResult>(Task<TResult>[])

    所有任务对象都已完成时,创建一个新的任务并执行

    7、WhenAny(IEnumerable<Task>)、WhenAny(Task[])、WhenAny<TResult>(IEnumerable<Task<TResult>>)、WhenAny<TResult>(Task<TResult>[])

    所有任务对象任何一个任务完成就创建一个新的任务并执行

    TaskFactory常用方法

    1、ContinueWhenAll(Task[], Action<Task[]>)、ContinueWhenAll(Task[], Action<Task[]>, CancellationToken)、ContinueWhenAll(Task[], Action<Task[]>, CancellationToken, TaskContinuationOptions, TaskScheduler)、...

    所有任务对象都已完成时,创建一个新的任务并执行   与Task.WhenAll方法 作用相当

    2、ContinueWhenAny(Task[], Action<Task>)、ContinueWhenAny<TAntecedentResult>(Task<TAntecedentResult>[], Action<Task<TAntecedentResult>>)、...

    所有任务对象任何一个任务完成就创建一个新的任务并执行 与Task.WhenAny方法 作用相当

    微软文档:

    Task:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.task?view=netframework-4.8

    TaskFactory:https://docs.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.taskfactory?view=netframework-4.8

  • 相关阅读:
    格式化数字,将字符串格式的数字,如:1000000 改为 1 000 000 这种展示方式
    jquery图片裁剪插件
    前端开发采坑之安卓和ios的兼容问题
    页面消息提示,上下滚动
    可以使用css的方式让input不能输入文字吗?
    智慧农村“三网合一”云平台测绘 大数据 农业 信息平台 应急
    三维虚拟城市平台测绘 大数据 规划 三维 信息平台 智慧城市
    农业大数据“一张图”平台测绘 大数据 房产 国土 农业 信息平台
    应急管理管理局安全生产预警平台应急管理系统不动产登记 测绘 大数据 规划 科教 三维 信息平台
    地下综合管廊管理平台测绘 大数据 地下管线 三维 信息平台
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11821327.html
Copyright © 2011-2022 走看看