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

  • 相关阅读:
    MySQL主从复制与读写分离
    使用PHPCMS搭建wap手机网站
    phpcms v9不用下插件自己做留言板
    css关于banner图轮播的实现
    MySql和Oracle的日期转换到底有哪些不同?我们来比较一下
    CSS---解决内容过多就会出文本溢出(显示在区域外面,不换行的情况)
    dedecms 后台发布后的文章不能编辑出现一片空白的解决办法
    python常识系列11-->python发送邮件基础
    python常识系列10-->python代码注释规范
    python常识系列09-->logging模块之handlers的使用
  • 原文地址:https://www.cnblogs.com/Dewumu/p/11821327.html
Copyright © 2011-2022 走看看