C#编程⾼并发的⼏种处理⽅法
并发(英⽂Concurrency),其实是⼀个很泛的概念,字⾯意思就是“同时做多件事”,不过⽅式有所不同。在.NET的世界⾥⾯,处理⾼并发⼤致有以下⼏种⽅法:
1,异步编程
异步编程就是使⽤future模式(⼜称promise)或者回调机制来实现(Non-blocking on waiting)。如果使⽤回调或事件来实现(容易callback hell),不仅编写这样的代码不直观,很快就容易把代码搞得⼀团糟。
不过在.NET 4.5 及以上框架中引⼊的async/await关键字(在.NET 4.0中通过添加Microsoft.Bcl.Async包也可以使⽤),让编写异步代码变得容易和优雅。通过使⽤async/await关键字,可以像写同步代码那样编写异步代码,所有的回调和事件处理都交给编译器和运⾏时帮你处理了,简单好⽤。
使⽤异步编程有两个好处:不阻塞主线程(⽐如UI线程),提⾼服务端应⽤的吞吐量。所以微软推荐ASP.NET中默认使⽤异步来处理请求。
例如:我⽤异步做模板消息推送。
/// <summary>
/// 使⽤异步Action测试异步模板消息接⼝
/// </summary>
/// <param name="checkcode"></param>
/// <returns></returns>
public async Task<string> TemplateMessageAsync(string openId, string first, string keyword1, string keyword2, string keyword3, string keyword4, string remark, string url) {
if (openId == null)
{
await和async使用方法return ReturnString(7771, "OPENID不能为空");
}
else
{
var testData = new //TestTemplateData()
{
first = new TemplateDataItem(first),
keyword1 = new TemplateDataItem(keyword1),
keyword2 = new TemplateDataItem(keyword2),
keyword3 = new TemplateDataItem(keyword3),
keyword4 = new TemplateDataItem(keyword4),
remark = new TemplateDataItem(remark)
};
var result = await TemplateApi.SendTemplateMessageAsync(_wechat.APPID, openId, "m6td4jp_heMA5rhopbUaHApOlp2DD5x18BMXWKj3M5U", url, testData);
return ReturnString(0, "成功");
}
}
2,并⾏编程
并⾏编程的出现实际上是随着CPU有多核⽽兴起的,⽬的是充分利⽤多核CPU的计算能⼒。并⾏编程由于会提⾼CPU的利⽤率,更适合客户端的⼀些应⽤,对于服务端的应⽤可能会造成负⾯影响(因为服务器本⾝就具有并⾏处理的特点,⽐如IIS会并⾏的处理多个请求)。我⾃⼰使⽤并⾏编程最多的场景是之前分析环境数据不确定度的时候,使⽤并⾏的⽅式计算蒙特卡洛模拟(计算上千次之后拟合),当然后来我使⽤泰勒级数展开来计算不确定度,没有这么多的计算量就⽆需并⾏了。当然在计算多⽅案结果⽐较的情况下,还是继续使⽤了并发计算。
在.NET中,并⾏的⽀持主要靠.NET 4.0引⼊的任务并⾏库和并⾏LINQ。通过这些库可以实现数据并⾏处理(处理⽅式相同,输⼊数据不同,⽐如我上⾯提到的应⽤场景)或者任务并⾏处理(处理⽅式不同,且数据隔离)。通过使⽤并⾏处理库,你不⽤关⼼Task的创建和管理(当然更不⽤说底层的线程了),只需要关注处理任务本⾝就⾏了。
3,响应式编程
响应式编程最近成为了⼀个Buzzword,其实微软6年前就开始给.NET提供⼀个Reactive Extensions了。⼀开始要理解响应式编程有点困难,但是⼀旦理解了,你就会对它的强⼤功能爱不释⼿。简单来说,响应式编程把事件流看作数据流,不过数据流是从IEnumable中拉取的,⽽事件流是从IObservable推送给你的。为什么响应式编程可以实现并发呢?这是因为Rx做到线程不可知,每次事件触发,后续的处理会从线程池中任意取出⼀个线程来处理。且可以对事件设置窗⼝期和限流。举个例⼦,你可以⽤Rx来让搜索⽂本框进⾏延迟处理(⽽不⽤类似我很早的时候⽤个定时器来延迟了)。
4,数据流编程
数据流(DataFlow)编程可能⼤家就更陌⽣了,不过还是有些常⽤场景可以使⽤数据流来解决。数据流其实是在任务并⾏库(TPL)上衍⽣出来的⼀套处理数据的扩展(也结合了异步的特性),TPL也是处理并⾏编程中任务并⾏和数据并⾏的基础库。
望⽂⽣义,TPL DataFlow就是对数据进⾏⼀连串处理,⾸先为这样的处理定义⼀套⽹格(mesh),⽹格中可以定义分叉(fork)、连接(join)、循环(loop)。数据流⼊这样的处理⽹格就能够并⾏的被处理。你可以认为⽹格是⼀种升级版的管道,实际上很多时候就是被当作管道来使⽤。使⽤场景可以是“分析⽂本⽂件中词频”,也可以是“处理⽣产者/消费者问题”。
5,Actor模型
Scala有Akka,其实微软研究院也推出了Orleans来⽀持了Actor模型的实现,当然也有Akka.NET可⽤。Orleans设计的⽬标是为了⽅便程序员开发需要⼤规模扩展的云服务, 可⽤于实现DDD+EventSourcing/CQRS系统。

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。