C#线程模型脉络

  今天在看同事新买到的《C#本质论 Edition 4》的时候,对比下以前Edtion3的新特性时,针对Async/Await关键字时发现对一些线程方面的定义还理解的不是很透彻,脉络还不是很清晰,这样有了本文,希望对有同样困惑的朋友有些帮助。

      文中部分内容摘取自《Essential C# 5.0 Edition 4》,还有一些我个人的对线程方面知识的理解与概括,如果有错误的地方还请指出,如果您觉得文章还不错,请点击“推荐” :)

C#线程模型脉络

缩写:

SPM:Synchronous Programming Mode,同步编程模型。

APM:Asynchronous Programming Mode,异步编程模型。(.Net 1.x的版本可以使用)

EAP:Event-Based Asynchronous Programming,基于事件的异步编程。(.Net Framework2.0中引入)

TAP:Task-Based Asynchronous Programming,基于任务的异步编程。(.Net Framework4.0中引入)

 

         C#的编程模型从SPM发展到APM编程模型,是Winform发展过程中解决界面由于同步执行长时间任务而导致界面“卡住”而发展而来(这里插一句个人对技术的理解:技术的发展总是在旧事物不能得到满足的情况下发展而来,新事物总是在特定的场合“出现”,并更好的代替了旧事物,所以,如果想了深入了解一个新事物的特性,必然要了解其发展脉络以及适用的场景),有了异步编程模式之后,人们又开始探索如何能更好的管理线程,更简单的适用,于是有了类似Background Worker和async/await一类的特性。

C#线程的编程模型到这里也就结束了,如果你有这方面的经验可能都觉得以上都是“废话”,或者“一言以概之”,的确,我不反对,但是有时候写文章有些时候不仅仅是炫耀技术,更多的是总结、归纳,理解的东西不一定说的出来,说出来的东西不一定真正理解!

         下面,针对每个内容做一个小结,老鸟飞过:)

SPM同步编程模型

         Winform程序基于消息泵机制,依次执行从“消息泵”中取出的数据”,当某一消息需耗费大量系统资源去执行,则下一条消息不得不等待,这样会造成程序界面“挂起”,这就是同步执行任务的一种模型,当然这只是同步模型下的一种劣势,其实现实中我们同步模型我们无时无刻不在用,包括编写的代码、执行的业务逻辑等。

APM异步编程模型

         为了解决同步模型中由于执行耗时任务而不得不等待的问题,产生了异步编程模式,其核心思想就是将耗时任务交付给其他“线程”去做,释放主线程。这里多出两句,在操作系统级别上Windows采用分时、多核以及多线程等技术来充分利用系统资源;在C#语言上由Thread发展到Task,Task是更高级的对Thread封装,提升资源利用率,有了这些基础才有更广阔的空间。

BeginXXX和EndXXX

使用BeginXXX和EndXXX实现基本的异步模式。

 

    class Program{static void Main(string[] args){string url = "http://www.cnblogs.com/cuiyansong/";if (args.Length > 0)url = args[0];Console.WriteLine(url);var webRequest = System.Net.WebRequest.Create(url);IAsyncResult asyncResult = webRequest.BeginGetResponse(null, null);while (!asyncResult.AsyncWaitHandle.WaitOne(200)){Console.WriteLine(".");}var webResponse = webRequest.EndGetResponse(asyncResult);using (System.IO.StreamReader reader = new System.IO.StreamReader(webResponse.GetResponseStream())){var bytes = Encoding.UTF8.GetBytes(reader.ReadToEnd());int length = bytes.Length;Console.WriteLine(length);}Console.Read();}}

 

TPL+APM模式

TPL:Task Parallel Library 任务并行库,其对task进行扩展,类似于ThreadPool。

这个模式是利用TaskFactory进行并行计算(下载)的例子,这个例子很有意思,很复古的感觉,有情趣的拷贝代码看看运行效果~~~

 

    class Program{private static object ConsoleSyncObj = new object();static void Main(string[] args){string[] urls = args;if (args.Length == 0){urls = new string[]{"http://www.cnblogs.com/cuiyansong/","https://github.com/Cuiyansong","http://www.cnblogs.com/",};}Task[] tasks = new Task[urls.Length];for (int i = 0; i < tasks.Length; i++){tasks[i] = DisplayPageSizeAsync(urls[i], i);}while (!Task.WaitAll(tasks, 50)){DisplayProgress(tasks);}Console.SetCursorPosition(0, urls.Length);Console.Read();}private static void DisplayProgress(Task[] tasks){for (int i = 0; i < tasks.Length; i++){if (!tasks[i].IsCompleted){DisplayProgress((WebRequestState)tasks[i].AsyncState);}}}private static void DisplayProgress(WebRequestState state){lock (ConsoleSyncObj){int left = state.ConsoleColumn;int top = state.ConsoleLine;if (left > Console.BufferWidth - int.MaxValue.ToString().Length){left = state.Url.Length;Console.SetCursorPosition(left, top);Console.Write("".PadRight(Console.BufferWidth - state.Url.Length));state.ConsoleColumn = left;}Write(state, ".");}}private static string FormatBytes(long bytes){string[] magintudes = new string[] { "GB", "MB", "KB", "Bytes" };long max = (long)Math.Pow(1024, magintudes.Length);return string.Format("{1:##.##} {0}", magintudes.FirstOrDefault(mag => bytes > (max /= 1024)) ?? "0 Bytes", (decimal)bytes / (decimal)max).Trim();}private static Task<System.Net.WebResponse> DisplayPageSizeAsync(string url, int i){var webRequest = System.Net.WebRequest.Create(url);var requestState = new WebRequestState(webRequest, i);Write(requestState, url + "  ");return Task<System.Net.WebResponse>.Factory.FromAsync(webRequest.BeginGetResponse, GetResponseAsyncCompleted, requestState);}private static WebResponse GetResponseAsyncCompleted(IAsyncResult asyncResult){WebRequestState completedState = (WebRequestState)asyncResult.AsyncState;HttpWebResponse response = (HttpWebResponse)completedState.WebRequest.EndGetResponse(asyncResult);using (StreamReader reader = new StreamReader(response.GetResponseStream())){int length = reader.ReadToEnd().Length;Write(completedState, FormatBytes(length));}return response;}private static void Write(WebRequestState completedState, string text){lock (ConsoleSyncObj){Console.SetCursorPosition(completedState.ConsoleColumn, completedState.ConsoleLine);Console.Write(text);completedState.ConsoleColumn += text.Length;}}private class WebRequestState{public System.Net.WebRequest WebRequest { get; private set; }public int ConsoleLine { get; set; }public int ConsoleColumn { get; set; }public string Url{get{return WebRequest.RequestUri.ToString();}}public WebRequestState(System.Net.WebRequest request){WebRequest = request;}public WebRequestState(System.Net.WebRequest request, int line){WebRequest = request;ConsoleLine = line;ConsoleColumn = 0;}}}

 

BackgroundWorker模型

针对经常出现任务委托后,执行任务并返回进度的需求,提供了BackgroundWorker类,节省开发时间。

 

    class Program{static void Main(string[] args){/****************************************************************************** 由于是演示,并为增加对BackgroundWorker取消等功能,这里只是简单演示。* 详细请参考:http://www.cnblogs.com/RoyYu/archive/2011/08/10/2133309.html* ***************************************************************************/System.ComponentModel.BackgroundWorker worker = new System.ComponentModel.BackgroundWorker();worker.WorkerReportsProgress = true;//报告完成进度worker.WorkerSupportsCancellation = true;//允许用户终止后台线程worker.DoWork += (sender, e) =>{for (int i = 0; i < 10; i++){System.Threading.Thread.Sleep(500);worker.ReportProgress(i, i);}};worker.ProgressChanged += (sender, e) =>{Console.WriteLine(string.Format("完成百分比。。。{0}", e.ProgressPercentage / (float)10));};worker.RunWorkerCompleted += (sender, e) =>{if (!e.Cancelled && e.Error == null){Console.WriteLine("处理成功,请按任意键返回。");}else{Console.WriteLine("处理中断,请按任意键返回。");}};worker.RunWorkerAsync();Console.Read();}}

复制代码

Async/Await模型

这回用窗体程序进行演示,对比起来效果会更明显些。

复制代码

    public partial class MainWindow : Window{List<string> urls = new List<string>();public MainWindow(){InitializeComponent();urls = new List<string>(){"www.baidu.com","www.cnblogs.cn","www.stackoverflow.com",};}/// <summary>/// 同步执行示例:当点击Button后,界面挂起,等待执行完毕后显示全部内容。/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private void Button_Click1(object sender, RoutedEventArgs e){InfoList.Text = "Ping....." + System.Environment.NewLine;Ping p = new Ping();foreach (var item in urls){PingReply pingRelay = p.Send(item);InfoList.Text += string.Format("Host Name: {0},Roundtrip Time: {1},Status: {2}", item, pingRelay.RoundtripTime.ToString(), pingRelay.Status + System.Environment.NewLine);}}/// <summary>/// 异步执行示例:当点击Button后,界面不挂起,界面滚动显示信息。/// </summary>/// <param name="sender"></param>/// <param name="e"></param>private async void Button_Click2(object sender, RoutedEventArgs e){InfoList.Text = "Ping....." + System.Environment.NewLine;Ping p = new Ping();foreach (var item in urls){PingReply pingRelay = await p.SendPingAsync(item);InfoList.Text += string.Format("Host Name: {0},Roundtrip Time: {1},Status: {2}", item, pingRelay.RoundtripTime.ToString(), pingRelay.Status + System.Environment.NewLine);}}}

复制代码

结语

下载源代码,请点击这里。

文章内容确实不是很深入,但对理解Winform的异步线程模型还是很有帮助的,今后有时间会针对线程单独来分享,希望各位看官不吝赐“赞”,水平有限,有问题欢迎提问:)

引用

  1. 文中部分例子出自《Essential C# 5.0 Edition 4》
  2. BackgrounWorker例子:http://www.cnblogs.com/RoyYu/archive/2011/08/10/2133309.html

 

作者:Stephen Cui 
出处:http://www.cnblogs.com/cuiyansong 

版权声明:文章属于本人及博客园共有,凡是没有标注[转载]的,请在文章末尾加入我的博客地址。 

如果您觉得文章写的还不错,请点击“推荐一下”,谢谢。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/438433.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

“菜”鸟理解.NET Framework(CLI,CLS,CTS,CLR,FCL,BCL)

既然要学.NET&#xff0c;就要先认识认识她&#xff0c;我不喜欢大段大段文字的东西&#xff0c;自己通过理解&#xff0c;画个图&#xff0c;来看看.NET的沉鱼落雁&#xff0c;闭月羞花之容。 最下层蓝色部分是.NET Framework的基础&#xff0c;也是所有应用软件的基础。.NET …

QQ炫舞手游显示进入服务器失败6,qq炫舞手游进不去怎么办 游戏进不去方法详解[多图]...

qq炫舞手游是新出的游戏&#xff0c;在近期非常的火爆&#xff0c;不过有不少的玩家都有进不了游戏的情况&#xff0c;下面安族小编给大家介绍一下游戏进不去方法详解。qq炫舞手游玩不了解决方法1.第一种方式就是内测还没有开启咯&#xff0c;所以玩家一般都是下载不到包的&…

那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)

一. 背景 在刚接触开发的头几年里&#xff0c;说实话&#xff0c;根本不考虑多线程的这个问题&#xff0c;貌似那时候脑子里也有没有多线程的这个概念&#xff0c;所有的业务都是一个线程来处理&#xff0c;不考虑性能问题&#xff0c;当然也没有考虑多线程操作一条记录存在的并…

asp.net mvc webform和razor的page基类区别

接触过asp.net mvc的都知道&#xff0c;在传统的webform的模式下&#xff0c;page页面的基类是这样声明的&#xff1a; <% Page Language"C#" MasterPageFile"~/Views/Shared/Site.Master" Inherits"ViewPage" %> 如果是partial view的话…

frameset ajax,js控制frameSet示例

js控制frameSet示例1&#xff1a;js修改frameset的cols属性来达到修改各个页面所占的宽高&#xff0c;例如隐藏当前frame页。复制代码 代码如下:window.parent.document.getElementsByTagName("frameset")[0].cols"0,*";2&#xff1a;js调用其他frame页面的…

人生的抉择—aspx、ashx、asmx文件处理请求效率比较

总结&#xff1a; ashx&#xff1a;只是实现IHttpHandler接口 aspx&#xff1a;public class Page : TemplateControl, IHttpHandler 而TemplateControl是&#xff1a; abstract class TemplateControl : Control, INamingContainer, IFilterResolutionService 所以aspx是重型…

ajax jsp模糊查询源码,Ajax动态执行模糊查询功能

Ajax动态执行模糊查询功能 内容精选换一换Profiling采集的数据较多&#xff0c;同时解析后展示的性能指标项也比较多&#xff0c;为方便用户快捷查找到具体性能指标的含义&#xff0c;提供命令行查询功能&#xff1a;不包含metric_name参数时&#xff0c;打印hiprof.sh脚本帮助…

一般处理程序(ashx)和页面处理程序(aspx)的区别

客官请看图 图中的Httphandler就是处理程序。 两者的共同点 如果把aspx处理程序和ashx处理程序放到上图中&#xff0c;他们是处在相同的位置的&#xff0c; 他们都实现了IHttphandler接口。实现了IHttphandler才具备处理请求的能力 两者的不同点 微软对aspx下足了功夫&#…

怎么在微云服务器找一个文件,微云文件在哪里打开_怎么快速找到微云文件

微云文件在哪里打开&#xff0c;这个问题困扰了许多的朋友&#xff0c;今天小编带着教程走向大家&#xff0c;我们可以使用微云可以快速连接和预览在线文档&#xff1b;同时加载和卸载多终端、手机、计算机、同步PAD数据传输&#xff0c;无需数据线。对于微云客户端&#xff0c…

ASP.NET Core真实管道详解[1]

ASP.NET Core管道虽然在结构组成上显得非常简单&#xff0c;但是在具体实现上却涉及到太多的对象&#xff0c;所以我们在 《ASP.NET Core管道深度剖析[共4篇]》 中围绕着一个经过极度简化的模拟管道讲述了真实管道构建的方式以及处理HTTP请求的流程。在这个系列 中&#xff0c;…

Wayland 显示服务器,wayland 1.8.0 发布,显示服务器

Wayland 1.8.0 发布&#xff0c;该版本现已提供下载&#xff1a; wayland-1.8.0.tar.xz&#xff1a;该版本与 RC2 相比的变化&#xff1a;publish-doc: Add script for publishing docs to the websiteconfigure.ac: bump to version 1.8.0 for the official releasescanner: d…

华为把服务器虚拟底层锁了,华为全面关闭解码锁服务:马上升级到很吓人的技术!...

原标题&#xff1a;华为全面关闭解码锁服务&#xff1a;马上升级到很吓人的技术&#xff01;华为余承东被网友称之为余大嘴&#xff0c;华为P20 Pro发布之后&#xff0c;余大嘴豪言华为P20的销量将超过2000万部&#xff0c;很就会推出一项“很吓人的技术”&#xff0c;没想到仅…

ASP.NET Core真实管道详解[2]:Server是如何完成针对请求的监听、接收与响应的【上】

Server是ASP .NET Core管道的第一个节点&#xff0c;负责完整请求的监听和接收&#xff0c;最终对请求的响应同样也由它完成。Server是我们对所有实现了IServer接口的所有类型以及对应对象的统称&#xff0c;如下面的代码片段所示&#xff0c;这个接口具有一个只读属性Features…

pos机未能连接服务器,pos 机链接不了服务器

pos 机链接不了服务器 内容精选换一换在本章节中&#xff0c;您将运行已部署好的游戏&#xff0c;登录游戏客户端。已准备好Windows机器&#xff0c;硬盘至少20G&#xff0c;且必须安装有显卡。服务器地址&#xff1a;节点的弹性IP地址&#xff0c;请登录CCE控制台&#xff0c;…

ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求

之所以称ASP.NET Core是一个Web开发平台&#xff0c;源于它具有一个极具扩展性的请求处理管道&#xff0c;我们可以通过这个管道的定制来满足各种场景下的HTTP处理需求。ASP. NET Core应用的很多特性&#xff0c;比如路由、认证、会话、缓存等&#xff0c;也同时定制消息处理管…

emui消息推送服务器,别再抱怨,这次或许真的轮到你了,EMUI9.1推送进度再次更新...

最近几年里&#xff0c;华为在系统方面下的功夫可谓是大家有目共睹的。以往大家在使用华为EMUI操作系统的时候&#xff0c;或许会感觉到卡顿、应用启动时间过长、运行不流畅以及UI界面毫无亮点可言等&#xff0c;但那已经是过去的EMUI系统了&#xff0c;今日的EMUI系统已与往日…

ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程

从《ASP.NET Core管道深度剖析&#xff08;1&#xff09;&#xff1a;采用管道处理HTTP请求》我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成&#xff0c;所以从总体设计来讲是非常简单的&#xff0c;但是就具体的实现来说&#xff0c;由于其中涉及很多对…

ASP.NET Core管道深度剖析(3):管道是如何处理HTTP请求的?

我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成&#xff0c;所以从总体设计来讲是非常简单的&#xff0c;但是就具体的实现来说&#xff0c;由于其中涉及很多对象的交互&#xff0c;我想很少人能够地把它弄清楚。为了让读者朋友们能够更加容易地理解管道…

ASP.NET Core管道深度剖析(4):管道是如何建立起来的?

在《管道是如何处理HTTP请求的&#xff1f;》中&#xff0c;我们对ASP.NET Core的请求处理管道的构成以及它对请求的处理流程进行了详细介绍&#xff0c;接下来我们需要了解的是这样一个管道是如何被构建起来的。这样一个管道由一个服务器和一个HttpApplication构成&#xff0c…

ASP.NET MVC 入门1、简介

什么是MVC模式 MVC&#xff08;Model-View-Controller&#xff0c;模型—视图—控制器模式&#xff09;用于表示一种软件架构模式。它把软件系统分为三个基本部分&#xff1a;模型&#xff08;Model&#xff09;&#xff0c;视图&#xff08;View&#xff09;和控制器&#xf…