浅谈多线程和异步

  最近很忙,因此拿出时间来写博客也算是忙里偷闲了,继承前面的一贯风格,继续浅谈胡侃。
  最近在项目中遇到了Socket异步网络传输的问题,所以沉下心来整理下。于是,先问了下度娘,结果找到了园友志良的一篇文章《C#中异步和多线程的区别》(参考文献1),精读了一遍,个人觉得理解的很好,自己学习下之余,又动手加工了一下以分享给各位博友,希望各位博友能对异步和多线程有一个清楚的认识。

  C#中异步和多线程的区别是什么呢?异步和多线程两者都可以达到避免调用线程阻塞的目的,从而提高软件的可响应性。甚至有些时候我们就认为异步和多线程是等同的概念。但是,异步和多线程还是有一些区别的。而这些区别造成了使用异步和多线程的时机的区别。  

  异步操作的本质

  所有的程序最终都会由计算机硬件来执行,所以为了更好的理解异步操作的本质,我们有必要了解一下它的硬件基础。 熟悉电脑硬件的朋友肯定对DMA这个词不陌生,硬盘、光驱的技术规格中都有明确DMA的模式指标,其实网卡、声卡、显卡也是有DMA功能的。DMA就是直 接内存访问的意思,也就是说,拥有DMA功能的硬件在和内存进行数据交换的时候可以不消耗CPU资源。只要CPU在发起数据传输时发送一个指令,硬件就开 始自己和内存交换数据,在传输完成之后硬件会触发一个中断来通知操作完成。这些无须消耗CPU时间的I/O操作正是异步操作的硬件基础。所以即使在DOS 这样的单进程(而且无线程概念)系统中也同样可以发起异步的DMA操作。

  线程的本质

  线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。

  异步操作的优缺点

  因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少 共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些出入,而且难以调试。

  多线程的优缺点

  多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。

  适用范围

  在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步 I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.net Remoting等跨进程的调用。

  而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。

  异步的一个示例

  大家可能都知道,使用delegate可以“自动”使一个方法可以进行异步的调用。从直觉上来说,我觉得是由编译器或者CLR使用了另外的线程来执行目标方法。到底是不是这样呢?

using System;
using System.Threading;
namespace 异步
{delegate void AsyncFoo(int i);class Program{/// ﹤summary﹥   /// 输出当前线程的信息   /// ﹤/summary﹥      /// ﹤param name="name"﹥方法名称﹤/param﹥    static void PrintCurrThreadInfo(string name){Console.WriteLine("Thread Id of " + name + " is: " + Thread.CurrentThread.ManagedThreadId + ", current thread is "+ (Thread.CurrentThread.IsThreadPoolThread ? "" : "not ") + "thread pool thread.");}/// ﹤summary﹥   /// 测试方法,Sleep一定时间   /// ﹤/summary﹥   /// ﹤param name="i"﹥Sleep的时间﹤/param﹥   static void Foo(int i){PrintCurrThreadInfo("Foo()");Thread.Sleep(i);}/// ﹤summary﹥   /// 投递一个异步调用   /// ﹤/summary﹥   static void PostAsync(){AsyncFoo caller = new AsyncFoo(Foo);caller.BeginInvoke(1000, new AsyncCallback(FooCallBack), caller);}static void Main(string[] args){PrintCurrThreadInfo("Main()");for (int i = 0; i < 5; i++){PostAsync();}Console.ReadLine();}static void FooCallBack(IAsyncResult ar){PrintCurrThreadInfo("FooCallBack()");AsyncFoo caller = (AsyncFoo)ar.AsyncState;caller.EndInvoke(ar);}}
}

程序的输出如下:

看样子答案是肯定的。

这个示例程序很好,基本上可以说是一个异步的使用规范模板了吧,个中含义不多说了。

参考文献:

C#中异步和多线程的区别

C#网络Socket编程(基本概念和操作) - Part.1,2,,3,4,5

题外话:
  经过将近3周(16天)的艰苦奋战,今天上午,终于把公司现有的一个项目升级成为异步,医院现场测试通过!其中涉及两块,一块是客户端的门诊医生站程序,另一块是服务器端!而后者的升级,对DebugLZQ现在所在的创业型公司来讲,也许提升的竞争力不是一点两点,因为不同的系统可以共用这个服务器!
  DebugLZQ也再一次真切的体会到了,实验室的产品走上商用,要经过的一些列的种种麻烦----网络传输速度、(大)数据并发、用户体验、数据库系统的可靠性、程序的稳定性(异常恢复)、软件系统安全性,甚至有时需要考虑到一些软硬件环境的问题。陪着“老板”一路走过来,着实不易!个中滋味,只有DebugLZQ知道。

  可能很快DebugLZQ就要离开现在的这个公司,因为马上要毕业了,还是希望师弟师妹们能把技术传承下去,也希望“老板”的公司茁壮成长,做强做大!

  

转载于:https://www.cnblogs.com/DebugLZQ/archive/2012/09/05/2670986.html

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

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

相关文章

查看Sql Server的log文件大小

SELECT DB_NAME(database_id) AS DatabaseName,Name AS Logical_Name,Physical_Name, (size*8)/1024 SizeMBFROM sys.master_filesWHERE DB_NAME(database_id) AdventureWorksGO 转载于:https://www.cnblogs.com/top5/archive/2010/03/02/1676776.html

python调用带参函数_Python | 带有示例的函数调用类型

python调用带参函数There are following types of function calls in python: python中有以下类型的函数调用&#xff1a; Call by value 按价值致电 Call by reference 通过参考电话 1)按价值致电 (1) Call by value ) When, we call a function with the values i.e. pass …

ffmpeg 命令添加文字水印

使用ffplay 预览一下效果&#xff1a; ffplay -i cctvhttp.flv -vf “drawtextfontsize100:fontfileArial.ttf:tex t‘hello world’:x20:y20:fontcolorblue:alpha0.5” -x 640 -y 480 使用ffmpeg保存为文件 &#xff1a; ffmpeg -i cctvhttp.flv -vf “drawtextfontsize10…

jquery弹出层

这是一个弹出层的插件&#xff0c;有时候做东西的&#xff0c;经常会用到了&#xff0c;所以在次发一下&#xff0c;和大家分享一下&#xff01; [task]<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/x…

MUL与IMUL区别(微机原理与接口技术 第2版)课后习题3.14、P123

MUL与IMUL的详细区别 乘数位数隐含的被乘数乘积的存放位置举例8位ALAX中MUL BL16位AXDX与AX中&#xff08;DX存放高16位、AX存放低16位&#xff09;MUL BX 课本P97例题 一&#xff09;、将以下指令中的立即数看作是无符号数实现相乘: MOV AL,0B4H ;ALB4H180 解释以下&…

SDL_main导致main找不到入口

SDL main的错误 引用SDL.h就会报这个错误 因为SDL 将main 宏定义为 SDL_main,所以会找不到main入口 可以使用#undef main取消这个宏定义

Java MathContext类| hashCode()方法与示例

MathContext类的hashCode()方法 (MathContext Class hashCode() method) hashCode() method is available in java.math package. hashCode()方法在java.math包中可用。 hashCode() method is used to get the hash code value of this MathContext. hashCode()方法用于获取此M…

实验8 SQL Server 的存储过程

实验8 SQL Server 的存储过程一、实验目的 1.掌握使用T-SQL编程的方法 2.掌握使用T-SQL语句创建一个存储过程并验证 3.掌握创建和执行带参数的存储过程 4.熟练使用系统存储过程、系统函数 二、实验要求 1.创建一个不带参数的存储过程。 2.创建一个带参数的存储过程p_count。 三…

Oracle ——如何确定性能差的 SQL

http://www.toadworld.com/KNOWLEDGE/KnowledgeXpertforOracle/tabid/648/TopicID/TSQ7/Default.aspx 本文主要说明在应用程序内书写和调优 SQL 语句。假设&#xff0c;你已经知道你应用程序中的哪些 SQL 语句需要注意。事实上&#xff0c;这不太容易。那么&#xff0c;我们如何…

C#中的委托和事件(续)

http://www.cnblogs.com/JimmyZhang/archive/2007/09/23/903360.html 欢迎浏览本文的后续文章&#xff1a; C#中的委托和事件(续)PDF 浏览&#xff1a;http://www.tracefact.net/Document/Delegates-and-Events-in-CSharp.pdf文中代码在VS2005下通过&#xff0c;由于VS2003(.Ne…

Java LocalDate类| minusYears()方法与示例

LocalDate类minusYears()方法 (LocalDate Class minusYears() method) minusYears() method is available in java.time package. minusYears()方法在java.time包中可用。 minusYears() method is used to subtract the given years from this LocalDate and return the LocalD…

ffmpeg 命令添加图片水印

使用ffplay预览一下&#xff1a; ffplay -i cctvhttp.flv -vf “moviewatermark.png[watermark];[in][watermark]overlay x10:y10[out]” -x 640 -y 480 参数&#xff1a; 有两个过滤器movie\overlay movie&#xff1a;读取watermark.png输出 [watermark]可以理解自定义的的变…

实验9 SQL Server 的触发器

实验9 SQL Server 的触发器一、实验目的 1.了解触发器的触发过程和类型 2.通过执行SQL脚本&#xff0c;掌握创建触发器并测试触发器 3.掌握通过使用触发器维护数据完整性的方法。 二、实验要求 1.按指定要求创建触发器。 三、实验步骤 1.创建一个名为tr_age的触发器&#xff0…

struts2学习笔记二--准备struts2的学习和开发环境

准备struts2的学习和开发环境1 导包2 参照开发包自带的例子在web.xml文件中配置3 参照开发包自带的例子编写Action类和配置struts.xml文件<struts><package name"demo" namespace"/hello/word"><action name"test" class"cn…

C#实现动态桌面背景图片切换

问题描述&#xff1a;凝视桌面背景&#xff0c;突感如果桌面背景是变化的像win7一样&#xff0c;该多有意思啊。闹钟瞬间产生一个念头&#xff0c;用C#写一个动态切换桌面背景的图片。如何实现这个想法了&#xff0c;我思考了一会儿&#xff0c;想到了如下的一些需要解决的问题…

duration java_Java Duration类| withSeconds()方法与示例

duration java持续时间类withSeconds()方法 (Duration Class withSeconds() method) withSeconds() method is available in java.time package. withSeconds()方法在java.time包中可用。 withSeconds() method is used to represent this Duration with the given seconds. wi…

ffmpeg 命令画中画效果

画中画效果也是和图片水印一样使用movie配合overlay实现 使用ffplay预览一下&#xff1a; ffplay -i cctvhttp.flv -vf “moviecctvhttp.flv[subm];[in][subm]overlayx20:y30[o ut]” -x 640 -y 480 &#xff08;可以看到是有两层视频的&#xff09; 用个不同的视频再测试&…

实验10 SQL Server 数据备份/恢复

实验10 SQL Server 数据备份/恢复一、实验目的 1.了解数据库备份的过程和属性设置&#xff1b; 2.掌握应用企业管理器备份和恢复数据库&#xff1b; 3.掌握应用T-SQL备份和恢复数据库&#xff1b; 4.掌握数据导入/导出的方法。 二、实验要求 1.创建指定数据库的备份. 2.恢复数…

指针和数组

数组的概念与指针的概念联系非常解密。其实数组的标识相当于它的第一个元素的地址&#xff0c;就像一个指针相当于它所指向的第一个元素的地址&#xff0c;因此其实它们是同一个东西 int numbers [20];int * p;下面的赋值为合法的&#xff1a; p numbers; 这里指针p 和numbers…

程序集(初尝,也是为插件程序准备)

拓展名是EXE或者DLL的.net可执行程序称为程序集。 .net程序集与一般的EXE&#xff0c;DLL的区别在于&#xff0c;它包含有metadata。 私有程序集 位于应用程序的目录下。共享程序集 必须有一个特殊的版本号&#xff0c;唯一的名称&#xff0c;通常安装在全局程序集缓存&#xf…