一、CLR线程池基础

创建和销毁线程是一个昂贵的操作,所以CLR管理了一个线程池(thread pool),可以将线程池看成一个黑盒。

CLR初始化时,线程池中是没有线程的。线程的初始化与其他线程一样,但是在完成任务以后,该线程不会自行销毁,而是以挂起的状态返回到线程池。直到应用程序再次向线程池发出请求时,线程池里挂起的线程就会再度激活执行任务。

二、 ThreadPool的简单使用

可以直接将一个运算放到线程池的队列中进行工作;

2.1 调用方式

向线程池的队列中添加一个”工作项“以及可选的状态数据,可以通过下面的两种方式来进行异步的操作:

public static bool QueueUserWorkItem(WaitCallback callBack);

public static bool QueueUserWorkItem(WaitCallback callBack, object state);

2.2 使用示例

  {
public static void Excute()
{
Console.WriteLine("Main Thread:开始队列进入一个异步线程;");
ThreadPool.QueueUserWorkItem(ComputeBoundOp, 5);
Console.WriteLine("Main Thread:做主线程的其他任务任务;");
//模拟其他任务
Thread.Sleep(10000);
Console.WriteLine("Main Thread End;");
} private static void ComputeBoundOp(object state)
{
Console.WriteLine("In ComputeBoundOp: state={0}",state); //模拟其他任务
Thread.Sleep(20000);
Console.WriteLine("ComputeBoundOp Thread End;");
}
}

运行结果:

2.3 取消线程的操作
简单的操作实例
  public class CancellationDemo
{
/// <summary>
/// 构造一个CancellationTokenSource后,从它的Token属性中获得一个或多个CancellationToken实例,并传给你的操作,使操作可以取消
/// </summary>
public static void CancellationGo()
{
//构造一个CancellationTokenSource
CancellationTokenSource cts =new CancellationTokenSource(); //取消后的执行操作
cts.Token.Register(() => Console.WriteLine("canceled 1"));
cts.Token.Register(() => Console.WriteLine("canceled 2")); //放入线程池开始工作
ThreadPool.QueueUserWorkItem(x => Count(cts.Token, 100)); Console.WriteLine("press to cancel the operation");
Console.ReadLine();
cts.Cancel();
} /// <summary>
/// 计数
/// </summary>
/// <param name="token"></param>
/// <param name="countTo"></param>
private static void Count(CancellationToken token,Int32 countTo)
{
for (int i = 0; i < countTo; i++)
{
if (token.IsCancellationRequested)
{
Console.WriteLine("count is cancelled");
break;
}
Console.WriteLine(i);
Thread.Sleep(2000);
}
Console.WriteLine("count is done");
}
}

运行结果:

三、Task

很容易调用ThreadPool的QueueUserWorkItem方法发起一次异步的运算;但是,没有内建的机制让你知道操作在什么时候完成,也没有机制在操作完成时获得返回值;为了克服一些限制,引入了任务概念;

Task类是封装的一个任务类,内部使用的是ThreadPool类,提供了内建机制,让你知道什么时候异步完成以及如何获取异步执行的结果,并且还能取消异步执行的任务。

3.1 使用task和ThreadPool来完成相同的任务:

ThreadPool.QueueUserWorkItem(ComputeBoundOp, 5);

new Task(ComputeBoundOp,5).Start();

Task.Run(() => ComputeBoundOp(5));

3.2 Task的简单使用

public class TaskDemo
{
public void Excute()
{
long input = 10000000;
//创建一个task
Task<Int64> t1 = new Task<Int64>((x) => Sum((Int64) x),
input);
t1.Start(); //显示等待任务执行完毕
t1.Wait();
Console.WriteLine("task1 result is {0},主线程Id:{1}", t1.Result,Thread.CurrentThread.ManagedThreadId); //演示可以取消的任务
CancellationTokenSource cst=new CancellationTokenSource();
//创建一个task
Task<Int64> t2 = new Task<Int64>(()=> Sum(cst.Token,input));
t2.Start();
Thread.Sleep(1000);
cst.Cancel();
Console.WriteLine("task2 result is {0}", t2.Result); } private static Int64 Sum(Int64 n)
{
Int64 sum = 0;
for (;n>0; n--)
{
checked
{
sum += n;
}
}
Console.WriteLine("计算线程Id:{0}",Thread.CurrentThread.ManagedThreadId);
return sum;
} //创建可取消的任务
private static Int64 Sum(CancellationToken ct, Int64 n)
{
Int64 sum = 0;
for (; n > 0; n--)
{
// ct.ThrowIfCancellationRequested();
if (!ct.IsCancellationRequested)
{
checked
{
sum += n;
}
Thread.Sleep(10);
}
}
return sum;
}
}

运行结果:



我们可以发现,程序启动了一个新的线程来计算;

当我们添加了取消操作时,运算结果不同;

四、async和await

在.NET 4.5中引入的Async和Await两个新的关键字后,用户能以一种简洁直观的方式实现异步编程。甚至都不需要改变代码的逻辑结构,就能将原来的同步函数改造为异步函数。

在内部实现上,Async和Await这两个关键字由编译器转换为状态机,通过System.Threading.Tasks中的并行类实现代码的异步执行。

4.1 一个简单的例子

public  class DownLoadUrlAsync
{ public void Excute()
{
Console.WriteLine("this is before Excute,threadId is {0}", Thread.CurrentThread.ManagedThreadId);
var t = GetUrl().ContinueWith(task =>
{
Console.WriteLine("this is ContinueWith Excute,threadId is {0},result is {1}",
Thread.CurrentThread.ManagedThreadId, task.Result);
});
Console.WriteLine("this is Excute,threadId is {0},t IsCompleted is {1}", Thread.CurrentThread.ManagedThreadId,t.IsCompleted);
}
private static async Task<int> GetUrl()
{
var httpClient = new HttpClient(); var url = "https://www.cnblogs.com/";
Console.WriteLine("this is before GetUrl,threadId is {0}", Thread.CurrentThread.ManagedThreadId);
var res = await httpClient.GetByteArrayAsync(url);
Console.WriteLine("this is GetUrl,threadId is {0}", Thread.CurrentThread.ManagedThreadId);
return res.Length;
}
}

运行结果:

通过结果可以发现,程序启用了新的线程来完成我们的任务;

五、小结

1、C#可以使用多种语法实现多线程 Thread,ThreadPool,Task,async await;

2、多线程可以同时完成多个任务;可以使程序的响应速度更快;可以让占用大量处理时间的任务或当前没有进行处理的任务定期将处理时间让给别的任务;

C#多线程的简单理解的更多相关文章

  1. iOS 多线程的简单理解(4) 线程锁的简单使用

    要用到多线程 ,就不得不考虑,线程之间的交互,线程是否安全 推荐一个原文链接 是关于 线程锁的基本使用的  http://blog.csdn.net/qq_30513483/article/detai ...

  2. iOS 多线程的简单理解(1) 方式 :同步 异步

    最近遇到特别糟糕的面试,过程中提到多次对多线程的处理问题,并没有很好的给予答复和解决,所以在这里做个简单的备案: 期望能更加了解和熟练使用 多线程技术: 下面都是自己的总结,如果存在不对的,或者不足, ...

  3. iOS 多线程的简单理解(3)执行方式 + 执行对列 的组合

    通过对前面两偏线程理解的总结,自己对线程的理解也逐渐加深,梳理的清晰起来…… 通常在使用线程 的时候,都是要用到 执行对列,执行方式,执行任务, 现在开始新一轮的深入 3. 1. 1  同步 + 串行 ...

  4. iOS 多线程的简单理解(2) 队列 :串行 ,并行,MainQueue,GlobalQueue

    多线程队列是装载线程任务的队形结构.(系统以先进先出的方式调度队列中的任务执行 FIFO).在GCD中有两种队列: 串行队列.并发队列. 队列 :串行队列.并发队列,全局主对列,全局并发队列 2.1. ...

  5. cpu个数、核数、线程数、Java多线程关系的理解

    cpu个数.核数.线程数.Java多线程关系的理解 2017年12月08日 15:35:37 一 cpu个数.核数.线程数的关系 cpu个数:是指物理上,也及硬件上的核心数: 核数:是逻辑上的,简单理 ...

  6. 【原创】分布式之数据库和缓存双写一致性方案解析(三) 前端面试送命题(二)-callback,promise,generator,async-await JS的进阶技巧 前端面试送命题(一)-JS三座大山 Nodejs的运行原理-科普篇 优化设计提高sql类数据库的性能 简单理解token机制

    [原创]分布式之数据库和缓存双写一致性方案解析(三)   正文 博主本来觉得,<分布式之数据库和缓存双写一致性方案解析>,一文已经十分清晰.然而这一两天,有人在微信上私聊我,觉得应该要采用 ...

  7. input屏蔽历史记录 ;function($,undefined) 前面的分号是什么用处 JSON 和 JSONP 两兄弟 document.body.scrollTop与document.documentElement.scrollTop兼容 URL中的# 网站性能优化 前端必知的ajax 简单理解同步与异步 那些年,我们被耍过的bug——has

    input屏蔽历史记录   设置input的扩展属性autocomplete 为off即可 ;function($,undefined) 前面的分号是什么用处   ;(function($){$.ex ...

  8. 关于 Promise 的一些简单理解

    一.ES6 中的 Promise 1.JS 如何解决 异步问题? (1)什么是 同步.异步? 同步指的是 需要等待 前一个处理 完成,才会进行 下一个处理. 异步指的是 不需要等待 前一个处理 完成, ...

  9. git的简单理解及基础操作命令

    前端小白一枚,最近开始使用git,于是花了2天看了廖雪峰的git教程(偏实践,对于学习git的基础操作很有帮助哦),也在看<git版本控制管理>这本书(偏理论,内容完善,很不错),针对所学 ...

随机推荐

  1. 项目管理工具-OmniPlan 3 for Mac

    链接:https://pan.baidu.com/s/1tp_37fHXHwJuklL1nNSwig  密码:l0sf 激活迷药(里面自带的keygen不能用,用这个好使): Name: Appked ...

  2. Locust - A modern load testing framework https://locust.io/

    Locust - A modern load testing frameworkhttps://locust.io/

  3. 转换为CString

    CString a, b, c;c = a + b; 使用Format方法方便的实现int.float和double等数字类型转换为CString字符串. %c 单个字符 %d 十进制整数(int) ...

  4. django 2 ORM操作 ORM进阶 cookie和session 中间件

    ORM操作 ORM概念 对象关系映射(Object Relational Mapping,简称ORM)模式是一种为了解决面向对象与关系数据库存在的互不匹配的现象的技术. 简单的说,ORM是通过使用描述 ...

  5. 三个线程abc顺序执行

    1.使用synchronized悲观锁(秋招阿里的一个笔试题,应该写的比较复杂,然后就没有然后了o(╥﹏╥)o) public class ThreadThreadp { private int fl ...

  6. java nio Files.newDirectoryStream用法

    try(DirectoryStream<Path> dirStream = Files.newDirectoryStream(Paths.get(directory,"*.ts& ...

  7. jQuery BlockUI Plugin Demo 4(Element Blocking Examples)

    Element Blocking Examples This page demonstrates how to block selected elements on the page rather t ...

  8. Moq中注入dynamic方法出错

    1.dynamic不可以跨程序集使用 2.需要在Test的AssemblyInfo.cs中里加 [assembly: InternalsVisibleTo("DFYYDream.UI.Web ...

  9. jquery-easyui中改变【确认框控件的按钮文字】($.messager.confirm)

    根据API这句话,就很自然想到重写该方法,代码如下: $.messager.defaults = { ok: "通过", cancel: "不通过" ,widt ...

  10. hfile.block.cache.size - hbase调优

    1.一个regionserver上有一个blockcache和N个memstore,它们的大小之和必须小于heapsize* 0.8,否则hbase不能启动,因为仍然要留有一些内存保证其它任务的执行. ...