一、Task关键字解释

Task 类的表示的单个操作不会返回一个值,通常以异步方式执行。 Task 对象是一种的中心思想 基于任务的异步编程模式 首次引入.NET Framework 4 中。 因为由执行工作 Task 对象通常上异步执行一个线程池线程而不是以同步方式在主应用程序线程中,您可以使用 Status 属性,以及 IsCanceled, , IsCompleted, ,和 IsFaulted 属性,以此来确定任务的状态。 大多数情况下,lambda 表达式用于指定的任务是执行的工作。可以说在某种程度上类似于线程池,但比线程池更容易使用。

需要用到的程序集

mscorlib(在 mscorlib.dll 中)
System.Threading.Tasks(在 System.Threading.Tasks.dll 中)

二、Task和ThreadPool

Task是在ThreadPool的基础上推出的,ThreadPool中有若干数量的线程,如果有任务需要处理时,会从线程池中获取一个空闲的线程来执行任务,任务执行完毕后线程不会销毁,而是被线程池回收以供后续任务使用。当线程池中所有的线程都在忙碌时,又有新任务要处理时,线程池才会新建一个线程来处理该任务,如果线程数量达到设置的最大值,任务会排队,等待其他任务释放线程后再执行。线程池能减少线程的创建,节省开销。

看下面代码

    class Program
{
static void Main(string[] args)
{
for (int i = ; i <= ; i++)
{
//ThreadPool执行任务
ThreadPool.QueueUserWorkItem(new WaitCallback((obj) =>
{
Thread.Sleep();
Console.WriteLine($"第{obj}个执行任务");
}), i);
}
Console.ReadKey();
}
}
}

结果是:

相对于Thread优势:

1、代码简单

2、减少不必要的创建,降低开销

自身缺点:

ThreadPool不能控制线程的执行顺序,我们也不能获取线程池内线程取消/异常/完成的通知,即我们不能有效监控和控制线程池中的线程。

三、Task的使用

1、类厂调用

          Task t=  Task.Factory.StartNew(() =>
{
for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from lambda:" + i);
}
}); t.Wait(); for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from main:"+i);
}

一般的,如果我们不需要得到lambda的返回值,也不需要控制它和主线程中的线程关系,只要求它和主线程同时高效执行Task.Factory.StartNew就好,如果需要阻塞主线程,则需要给任务一个引用t,并在需要的地方调用阻塞方法Wait,WaitAll是针对任务链

2、Task的构造函数初始化 (可以添加第二个参数附加信息)

需要调用task,开始执行任务

          Task t=  new Task(() =>
{
for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from lambda:" + i);
}
}); t.Start(); for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from main:"+i);
} t.Wait();

3、Run

          Task t=  Task.Run(() =>
{
for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from lambda:" + i);
}
}); for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from main:"+i);
} t.Wait();

四、同步执行

Task提供了  task.RunSynchronously()用于同步执行Task任务

          Task t=  new Task(() =>
{
for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from lambda:" + i);
}
}); t.RunSynchronously(); for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from main:"+i);
} t.Wait();

五、有返回值

            Func<string> func = ()=>
{
System.Threading.Thread.Sleep();
return "from func";
}; Task<string> t= new Task<string>(func); t.Start(); for (int i = ; i < ; i++)
{
System.Threading.Thread.Sleep();
Console.WriteLine("from main:"+i);
} t.Wait(); Console.WriteLine(t.Result);

调用t.result的时候,调用线程会阻塞

六、Task任务的阻塞(Wait/WaitAll/WaitAny)

 Thread的Join方法可以阻塞调用线程,但是有一些弊端:①如果我们要实现很多线程的阻塞时,每个线程都要调用一次Join方法;②如果我们想让所有的线程执行完毕(或者任一线程执行完毕)时,立即解除阻塞,使用Join方法不容易实现。Task提供了  Wait/WaitAny/WaitAll  方法,可以更方便地控制线程阻塞。

task.Wait()  表示等待task执行完毕,功能类似于thead.Join();  Task.WaitAll(Task[] tasks)  表示只有所有的task都执行完成了再解除阻塞;  Task.WaitAny(Task[] tasks) 表示只要有一个task执行完毕就解除阻塞

如果将栗子中的WaitAll换成WaitAny,那么任一task执行完毕就会解除线程阻塞,执行结果是:先打印【线程1执行完毕】,然后打印【主线程执行完毕】,最后打印【线程2执行完毕】

七、Task任务的取消

1 Thread取消任务执行

在Task前我们执行任务采用的是Thread,Thread如何取消任务,可以建立一个key

 
        static void Main(string[] args)
{
bool key= false;
int index = 0;
Thread t= new Thread(() =>
{
while (!key)
{
Thread.Sleep(1000);
Console.WriteLine("thread operating....");
}
});
t.Start();
//五秒后取消任务执行
Thread.Sleep(5000);
key= true;
Console.ReadKey();
}
 

  Task中有一个专门的类 CancellationTokenSource  来取消任务执行,还是使用上边的例子,我们修改代码如下,程序运行的效果不变。

        static void Main(string[] args)
{
CancellationTokenSource source = new CancellationTokenSource();
int index = 0;
//开启一个task执行任务
Task task= new Task(() =>
{
while (!source.IsCancellationRequested)
{
Thread.Sleep(1000);
Console.WriteLine("task operating...");
}
});
task.Start();
//五秒后取消任务执行
Thread.Sleep(5000);
//source.Cancel()方法请求取消任务,IsCancellationRequested会变成true
source.Cancel();
Console.ReadKey();
}
 

有疑问请加qq群:568055323

C#深度学习のTask(基于任务的异步模型)的更多相关文章

  1. 深度学习之Attention Model(注意力模型)

    1.Attention Model 概述 深度学习里的Attention model其实模拟的是人脑的注意力模型,举个例子来说,当我们观赏一幅画时,虽然我们可以看到整幅画的全貌,但是在我们深入仔细地观 ...

  2. Task C# 多线程和异步模型 TPL模型 【C#】43. TPL基础——Task初步 22 C# 第十八章 TPL 并行编程 TPL 和传统 .NET 异步编程一 Task.Delay() 和 Thread.Sleep() 区别

    Task C# 多线程和异步模型 TPL模型   Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task ...

  3. .NET - 基于事件的异步模型

    注:这是大概四年前写的文章了.而且我离开.net领域也有四年多了.本来不想再发表,但是这实际上是Active Object模式在.net中的一种重要实现方法,因此我把它掏出来发布一下.如果该模型有新的 ...

  4. [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型

    [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 目录 [源码解析] 深度学习流水线并行 PipeDream(3)--- 转换模型 0x00 摘要 0x01 前言 1.1 改 ...

  5. 深度学习基础-基于Numpy的卷积神经网络(CNN)实现

    本文是深度学习入门: 基于Python的实现.神经网络与深度学习(NNDL)以及动手学深度学习的读书笔记.本文将介绍基于Numpy的卷积神经网络(Convolutional Networks,CNN) ...

  6. 深度学习基础-基于Numpy的多层前馈神经网络(FFN)的构建和反向传播训练

    本文是深度学习入门: 基于Python的实现.神经网络与深度学习(NNDL)以及花书的读书笔记.本文将以多分类任务为例,介绍多层的前馈神经网络(Feed Forward Networks,FFN)加上 ...

  7. 深度学习基础-基于Numpy的感知机Perception构建和训练

    1. 感知机模型   感知机Perception是一个线性的分类器,其只适用于线性可分的数据.          f(x) = sign(w.x + b) 其试图在所有线性可分超平面构成的假设空间中找 ...

  8. 【机器学习PAI实践十】深度学习Caffe框架实现图像分类的模型训练

    背景 我们在之前的文章中介绍过如何通过PAI内置的TensorFlow框架实验基于Cifar10的图像分类,文章链接:https://yq.aliyun.com/articles/72841.使用Te ...

  9. Task C# 多线程和异步模型 TPL模型

    Task,异步,多线程简单总结 1,如何把一个异步封装为Task异步 Task.Factory.FromAsync 对老的一些异步模型封装为Task TaskCompletionSource 更通用, ...

随机推荐

  1. oracle expdp自动备份脚本

    windows: @echo off echo ================================================ echo Windows环境下Oracle数据库的自动 ...

  2. 【译】《Clean C#》

    本文是<Clean C#>一书译文的序言,阅读译文请移步至:<Clean C#>译文. <Clean C#>的副标题是Readable,Maintainable,P ...

  3. T-SQL基础(四)之集合运算

    三个运算符 T-SQL支持三个集合运算符:UNION.INTERSECT.EXCEPT. 集合运算符查询的一般形式如下: Query1 <set_operator> Query2 -- 这 ...

  4. Python_简单三级菜单制作

    一:制作要求 1.三级菜单 2.可依次选择进入各子菜单 3.所需新知识点:字典,列表 *本文通过三种方法完成,第一种:只使用循环,第二种:使用列表,第三种:使用字典 二:FlowChart流程图 与上 ...

  5. js实现ctrl+v上传图片

    描述:实现类似QQ截图删上传图片的功能 a.需要的js插件 paste.image.js 地址:https://github.com/iyangyuan/pasteimg b.paste.image. ...

  6. JavaScript是如何工作: 深入探索WebSocket和HTTP/2与SSE + 如何选择正确的路径!

    原文:<JavaScript是如何工作: 深入探索 websocket 和HTTP/2与SSE +如何选择正确的路径! 作者:前端小智 Fundebug经授权转载,版权归原作者所有. 文章底部分 ...

  7. Duplicate entry '0' for key 'PRIMARY'

    一般使用ORM时,提交新增实体时, mysql会出现此错误:Duplicate entry '0' for key 'PRIMARY' 原因是插入语句,未提供主键的值,且主键是非自增长的. 解决办法是 ...

  8. Android为TV端助力 bitmap和数据流的互转

    Bitmap aa = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher); InputStream input ...

  9. Ubuntu下解压缩文件

    记录Ubuntu下各种压缩和解压方式: .tar解包:tar xvf FileName.tar打包:tar cvf FileName.tar DirName(注:tar是打包,不是压缩!)—————— ...

  10. Testlink1.9.17使用方法(第十一章 其他易用性功能)

    第十一章 其他易用性功能 QQ交流群:585499566 一. 自定义 一). 自定义字段管理 在主页点击[自定义字段管理]按钮-->进入自定义字段管理页面,点击[创建]按钮,可以创建一个字段, ...