一、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. 安卓P2P开源项目

    https://github.com/LinYaoTian/P2PChat 一个基于局域网的 Android P2P 聊天系统 https://github.com/ddssingsong/webrt ...

  2. Qt编写自定义控件51-可输入仪表盘

    一.前言 这个控件是近期定制的控件,还是比较实用的控件之一,用户主要是提了三点需求,一点是切换焦点的时候控件放大突出显示,一点是可直接输入或者编辑值,还有一点是支持上下键及翻页键和鼠标滚轮来动态修改值 ...

  3. PAT 甲级 1056 Mice and Rice (25 分) (队列,读不懂题,读懂了一遍过)

    1056 Mice and Rice (25 分)   Mice and Rice is the name of a programming contest in which each program ...

  4. C++ - 第一个程序

    代码: #include <iostream> using namespace std; int main() { cout << "hello!" < ...

  5. html的css背景图的repeat

    HTML里background-image中,可以设置background-repeat实现平铺,前面博文中关于css样式换行的(相关博文:超文本css样式换行),其中有个三个div组合的,中间的di ...

  6. idea的enable auto-import/内存设置

    设置pom.xml依赖的自动导入 设置idea的memory heap On the Help menu, click Edit Custom VM Options. Set the -Xmx opt ...

  7. Direct2D 学习笔记(1)概述

    Direct2D 应用程序接口概述 资源网站 https://docs.microsoft.com/en-us/windows/win32/Direct2D/the-direct2d-api 主要用到 ...

  8. python全栈索引

    书签 python基础 太白金星 TigerLee python基础一 pytcharm安装详细教程 python基础二 python基础数据类型 Python最详细,最深入的代码块小数据池剖析 深浅 ...

  9. 【计算机视觉】OPENCV对于有alpha通道的透明背景图片的读取和图片叠加

    这个是我自己做的粗略的螺旋丸的图,导出为png并带有alpha通道. 最后和一只狗合成成这个样子. 效果还是可以的. 为了实现这个效果,首先我们要明白具有透明通道的图片的OpenCV的读取方式.在Op ...

  10. 动态规划算法(Dynamic Programming,简称 DP)

    动态规划算法(Dynamic Programming,简称 DP) 浅谈动态规划 动态规划算法(Dynamic Programming,简称 DP)似乎是一种很高深莫测的算法,你会在一些面试或算法书籍 ...