第一章 管理程序流(In .net4.5) 之 实现多线程和异步处理
1. 概述
本章主要讲解.net4.5如何实现多线程和异步处理的相关内容。
2. 主要内容
2.1 理解线程
① 使用Thread类
public static class Program
{
public static void ThreadMethod()
{
for (int i = ; i < ; i++)
{
Console.WriteLine(“ThreadProc: {}”, i);
Thread.Sleep();
}
}
public static void Main()
{
Thread t = new Thread(new ThreadStart(ThreadMethod));
t.Start();
for (int i = ; i < ; i++)
{
Console.WriteLine(“Main thread: Do some work.”);
Thread.Sleep();
}
t.Join();
}
}
*Thread.Join()方法的调用是通知主线程等待,直到其他线程执行完毕。
*Thread.Sleep(0)是标记当前线程的状态为完成,这样系统就可以立即切换到其他线程了。
② 如果某线程的IsBackground属性设置为true,主程序退出前将不会考虑该线程是否还在执行。
③ 使用ParameterizedThreadStart委托,可以通过线程的start方法传递数据。
④ 用ThreadStatic Attribute 标记一个属性,每个使用该属性的线程都会获得一个该属性的副本。
⑤ 使用ThreadLocal<T>类,你可以定义线程本地数据,并且为每一个线程单独初始化。
public static class Program
{
public static ThreadLocal<int> _field =
new TheadLocal<int>(() =>
{
return Thread.CurrentThread.ManagedThreadId;
}); public static void Main()
{
new Thread(() =>
{
for (int x=; x < _field.value; x++)
Console.WriteLine("Thread A: {0}", x);
}).Start(); new Thread(() =>
{
for (int x=; x < _field.value; x++)
Console.WriteLine("Thread B: {0}", x);
}).Start(); Console.ReadKey();
}
}
⑥ 线程池
提供线程的管理和重用。Web服务器接收请求,就是一个使用线程池的典型的例子。
2.2 使用Task
使用Task类,可以知道线程的完成状态以及接收返回值。
① 使用ContinueWith方法,可以实现任务完成之后的后续任务。
Task<int> t = Task.Run(() => { return ; });
t.ContinueWith(() => { Console.WriteLine("Canceled");},
TaskContinationOptions.OnlyOnCanceled);
t.ContinueWith(() => { Console.WriteLine("Faulted");},
TaskContinationOptions.OnlyOnFaulted);
② Task还可以嵌套子任务。
③ TaskFactory可以批量管理Task。
2.3 使用Parallel类
Parallel类有一对儿静态方法For、ForEach和Invoke方法,可以用这些来实现并行任务。
Parallel.For(, , i =>
{
Thread.Sleep();
}); var numbers = Enumerable.Range(, );
Parallel.ForEach(numbers, i =>
{
Thread.Sleep();
});
使用ParallelLoopState可以实现跳出循环(break())或者终止程序(Stop());
2.4 使用 async 和 await
这两个关键字用于简化异步代码逻辑。
用async标记的方法,就具备了可以被划分指定部分到多个线程去执行的功能。具体划分哪些部分,用await关键字来标记。
public static async Task<string> DownloadContent()
{
using (HttpClient client = new HttpClient())
{
string result = await client.GetStringAsync("http://www.z.cn");
return result;
}
}
不需要ui交互的时候,可以调用ConfigureAwait方法禁用SynchronizationContext,可以获得更好的体验。
* 标记了async的方法,里面要有await。
* 标记了async的方法,不要返回void。(async事件除外)
2.5 使用 Parallel Language Integrated Query (PLINQ)
使用PLINQ,可以将一个顺序查询转化为并行版本。
var numbers = Enumerable.Range(, );
var parallelResult = numbers.AsParallel()
.Where(i => i % == )
.ToArray();
使用AsOrdered操作,可以保证结果是有序的。
.net framework把并行过程中的异常都集中到了AggregateException 中。
2.6 使用并行集合(concurrent collections)
.net framework提供了一些线程安全的集合:
① BlockingCollection<T>
删除数据时会阻塞程序,添加数据比较快。
可以使用CompleteAdding方法通知其他被阻塞的线程。
public static void Main()
{
BlockingCollection<string> col = new BlockingCollection<string>();
Task read = Task.Run(() =>
{
foreach(string v in col.GetConsumingEnumerable())
Console.WriteLine(v);
}); Task write = Task.Run(() =>
{
while(true)
{
string s = Console.ReadLine();
if (string.IsNullOrWhiteSpace(s)) break;
col.Add(s);
}
}); write.wait();
}
② ConcurrentBag<T>
用副本方式支持并发。无序。
TryPeek方法在多线程中不太有用。peek过程中可能数据已经被修改了。
ConcurrentBag<int> bag = new ConcurrentBag<int>();
Task.Run(() =>
{
bag.Add();
Thread.Sleep();
bag.Add();
});
Task.Run(() =>
{
foreach(int i in bag)
Console.WriteLine(i);
}).wait();
*上面的程序仅打印42。因为向bag添加21的时候,打印程序已经执行完毕了。
③ ConcurrentQueue<T> 和 ConcurrentStack<T>
也是用快照方式实现。
④ ConcurrentDictionary
var dict = new ConcurrentDictionary<string, int>();
if (dict.TryAdd("k1", ))
Console.WriteLine("Added"); if (dict.TryUpdate("k1", , ))
Console.WriteLine("42 updated to 21"); dict["k1"] = ; //Overwhrite uncondictionally int r1 = dict.AddOrUpdate("k1", , (s, i) => i * );
int r2 = dict.GetOrAdd("k2", );
3. 总结
① 可以把每个线程当成一个独享cpu的程序。
② 建议使用ThreadPool来管理线程。
③ Task是对一个执行逻辑的封装。推荐用于多线程代码中。
④ Paralle用于代码中的并行操作。
⑤ PLINQ是LINQ的扩展,用于并行查询。
⑥ 用 async 和 await,可以用同步的形式编写异步的代码。
⑦ 并行集合可以线程安全的用于多线程环境中。
第一章 管理程序流(In .net4.5) 之 实现多线程和异步处理的更多相关文章
- 第二章 管理程序流(In .net4.5) 之 管理多线程
1. 概述 本章包括同步资源以及取消长时间任务相关的内容. 2. 主要内容 2.1 同步资源 ① lock关键字实现.会阻塞程序,有可能会导致死锁. ② volatile关键字可以禁用编译优化,用于避 ...
- 第五章 管理程序流(In .net4.5) 之 异常处理
1. 概述 本章包括.net4.5中异常处理相关的部分. 2. 主要内容 2.1 处理异常 ① try.cahtch.finally 机制,无需多言. ② 使用 Environment.FailFas ...
- 第三章 管理程序流(In .net4.5) 之 实现程序流
1. 概述 本章内容包括 布尔表达式.流控制方式.集合遍历 以及 流跳转. 2. 主要内容 *由于该章内容比较基础,日常用的也很多,故对一些常用的基础内容不再赘述. 2.1 使用布尔表达式 熟悉下列比 ...
- 第四章 管理程序流(In .net4.5) 之 事件和回调
1. 概述 本章讲解如何使用 委托.lambda表达式 和 匿名方法 来创建和使用事件. 2. 主要内容 2.1 理解委托 委托是一种用方法签名形式定义的类型.可以让它指向其他方法,可以通过它调用其他 ...
- File类与常用IO流第一章File类
第一章:File类 一.1个重点单词: file:文件:directory:文件夹/目录:path:路径(绝对路径:absolutePath) 二.4个静态成员变量: 1.static String ...
- 精通Web Analytics 2.0 (3) 第一章:网站分析的新奇世界
精通Web Analytics 2.0 : 用户中心科学与在线统计艺术 第一章:Web Analytics 2.0的新奇世界 多年以来,我们很清楚的知道,网站分析能够真正的改革网络上业务的完成方式.那 ...
- 《LINUX内核设计与实现》读书笔记之第一章和第二章
一.第一章 1. Unix内核的特点简洁:仅提供系统调用并有一个非常明确的设计目的抽象:几乎所有东西都被当做文件可移植性:使用C语言编写,使得其在各种硬件体系架构面前都具备令人惊异的移植能力进程:创建 ...
- 《SDN核心技术剖析和实战指南》第一章小结
第一章主要是概况.新技术有一个特点是,每家都有不同的说法.这里我只说说我比较认同的部分. SDN的核心概念大概有两个:转发面与控制面分离.开发可编程化.书里还说逻辑上集中控制,其实这个就可以从转发与控 ...
- [A Top-Down Approach][第一章 计算机网络和因特网]
[A Top-Down Approach][第一章 计算机网络和因特网] 标签(空格分隔): 计算机网络 介绍基本术语和概念 查看构成网络的基本硬件和软件组件. 从网络的边缘开始,考察在网络中运行的端 ...
随机推荐
- transform的使用
*:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...
- MFC学习 消息钩子使用
HANDLE h_KeyBoard; //当前进程的钩子, 另外WH_KEYBOARD_LL, 与WH_MOUSE_LL参数时, 是获取的底层的消息, 相当于获取的全局的 g_hKeyBoard = ...
- MFC学习 画图设置字体按钮风格
修改按钮样式时, 设置按钮关联哪个按钮类, 按钮类是自己写的, 从CButton继承, 重写DrawItem可修改按钮样式. 代码中包括画线, 点, 圆, 设置这些的样式, 如线粗, 颜色, 字体. ...
- 手机app测试之我见
app端功能测试不是单纯的点点点,在实际的工作中,测试小白需要从业务入手,熟悉基本测试点.测试技巧和方法,以点带面,从功能和思维入手,避免眼高手低: app端测试,首先我们需要考虑不同的机型系统.不同 ...
- jmeter随笔(10)-中文url编码问题
坚持分享,坚持总结,技术需要时间的积累和练习,对jmeter实践的点滴的记录,这里分享交流,仅供参考和讨论,有想法的欢迎留言.谈论,手机上图片如果不清晰,请点击[阅读原文]查看. 1技巧1:后台数据h ...
- 关于conversation generation的论文笔记
对话模型此前的研究大致有三个方向:基于规则.基于信息检索.基于机器翻译.基于规则的对话系统,顾名思义,依赖于人们周密设计的规则,对话内容限制在特定领域下,实际应用如智能客服,智能场馆预定系统.基于信息 ...
- 利用Oracle VM VirtualBox部署自己的owncloud存储服务器
最近在弄文档方面的工作,所以想找个能够自动备份且带历史版本的网盘,找了很久没找到,所以决定自己部署一个私人服务器. 找了很久.试了很久终于确定owncloud能够满足自己的要求,而且还是开源免费的. ...
- onenote网页版如何打开链接弄到客户端
1.网页登录https://onedrive.live.com 2.登录MS帐号 3.输入复制的分享链接,回车 4.点击编辑,在客户端编辑,弹出是否启动应用,点启动,等一段时间完成.
- SQL函数——LENGTH()和LENGTHB()
LENGTH()函数是比较简单同时也是非常有用的一个函数,在此小记一下,加深印象以备后用! 1:先上实验的例子——我新建了一张Student表,插入了若干条测试数据,如下图所示: 2:实验LENGTH ...
- android service 学习
参考:http://www.cnblogs.com/allin/archive/2010/05/15/1736458.html http://www.cnblogs.com/allin/archive ...