c# 多线程与异步调用
异步操作的本质
在方法调用前为异步方法指定一个回调函数,方法调用后被线程池中的一个线程接管,执行该方法。主线程立即返回,继续执行其他工作或响应用户请求。如果异步方法执行完 毕,回调函数被自动执行,以处理异步方法的调用结果。 如何实现异步方法呢?C#通过异步委托调用BeginInvoke和EndInvoke方法来实现异步方法。
BeginInvoke方法原型: IAsyncResult BeginInvoke(......, AsyncCallback callback, object o); ......表示异步委托中定义的参数列表。 AsyncCallback参数是一个用于 回调函数的委托,它的原型为: public delegate void AsyncCallback(IAsyncResult ar)。其中IAsyncResult参数用于包装异步方法的执行结果。 Object参数用于在主线程与回调函数间传递一些附加信息,如同步信息。
EndInvoke方法原型: xxx EndInvoke(IAsyncResult result); xxx表示异步委托原型中定义的返回数据类型,IAsyncResult用于包装异步方法的执行结果。
线程的本质
线程不是一个计算机硬件的功能,而是操作系统提供的一种逻辑功能,线程本质上是进程中一段并发运行的代码,所以线程需要操作系统投入CPU资源来运行和调度。
异步操作的优缺点
因为异步操作无须额外的线程负担,并且使用回调的方式进行处理,在设计良好的情况下,处理函数可以不必使用共享变量(即使无法完全不用,最起码可以减少共享变量的数量),减少了死锁的可能。当然异步操作也并非完美无暇。编写异步操作的复杂程度较高,程序主要使用回调方式进行处理,与普通人的思维方式有些初入,而且难以调试。
多线程的优缺点
多线程的优点很明显,线程中的处理程序依然是顺序执行,符合普通人的思维习惯,所以编程简单。但是多线程的缺点也同样明显,线程的使用(滥用)会给系统带来上下文切换的额外负担。并且线程间的共享变量可能造成死锁的出现。
适用范围
在了解了线程与异步操作各自的优缺点之后,我们可以来探讨一下线程和异步的合理用途。我认为:当需要执行I/O操作时,使用异步操作比使用线程+同步I/O操作更合适。I/O操作不仅包括了直接的文件、网络的读写,还包括数据库操作、Web Service、HttpRequest以及.Net Remoting等跨进程的调用。
而线程的适用范围则是那种需要长时间CPU运算的场合,例如耗时较长的图形处理和算法执行。但是往往由于使用线程编程的简单和符合习惯,所以很多朋友往往会使用线程来执行耗时较长的I/O操作。这样在只有少数几个并发操作的时候还无伤大雅,如果需要处理大量的并发操作时就不合适了。
下面看个异步调用的实例:
- using System;
- using System.Threading;
- namespace AsyncDelegateDemo
- {
- 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(, new AsyncCallback(FooCallBack), caller);
- }
- static void Main(string[] args)
- {
- PrintCurrThreadInfo("Main()");
- for(int i = ; i < ; i++)
- {
- PostAsync();
- }
- Console.ReadLine();
- }
- static void FooCallBack(IAsyncResult ar)
- {
- PrintCurrThreadInfo("FooCallBack()");
- AsyncFoo caller = (AsyncFoo) ar.AsyncState;
- caller.EndInvoke(ar);
- }
- }
- }
这段代码代码的输出如下:
- Thread Id of Main() is: , current thread is not thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of Foo() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
- Thread Id of FooCallBack() is: , current thread is thread pool thread.
c# 多线程与异步调用的更多相关文章
- 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource
1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...
- Java多线程实现异步调用
在Java平台,实现异步调用的角色有如下三个角色:调用者. 提货单 .真实数据,一个调用者在调用耗时操作,不能立即返回数据时,先返回一个提货单 .然后在过一断时间后凭提货单来获取真正的数据.去蛋糕店买 ...
- 衔接UI线程和管理后台工作线程的类(多线程、异步调用)
一个不错的UI多线程操作类 http://www.cnblogs.com/net66/archive/2005/08/03/206132.html
- 【摘要】多线程 - BeginInvoke异步调用
private delegate int MyMethod(); private int method() { Thread.Sleep(); ; } private void MethodCompl ...
- C# 多线程详解 Part.02(UI 线程和子线程的互动、ProgressBar 的异步调用)
我们先来看一段运行时会抛出 InvalidOperationException 异常的代码段: private void btnThreadA_Click(object sender, ...
- PHP中实现异步调用多线程程序代码
本文章详细的介绍了关于PHP中实现异步调用多线程方法,下面我们以给1000个用户发送一封推荐邮件,用户输入或者导入邮件账号了提交服务器执行发送来讲述. 比如现在有一个场景,给1000个用户发送一封推荐 ...
- 多线程编程学习笔记——异步调用WCF服务
接上文 多线程编程学习笔记——使用异步IO 接上文 多线程编程学习笔记——编写一个异步的HTTP服务器和客户端 接上文 多线程编程学习笔记——异步操作数据库 本示例描述了如何创建一个WCF服务,并宿主 ...
- MacOS和iOS开发中异步调用与多线程的区别
很多童鞋可能对Apple开发中的异步调用和多线程的区别不是太清楚,这里本猫将用一些简单的示例来展示一下它们到底直观上有神马不同. 首先异步调用可以在同一个线程中,也可以在多个不同的线程中.每个线程都有 ...
- 那些年我们一起追逐的多线程(Thread、ThreadPool、委托异步调用、Task/TaskFactory、Parallerl、async和await)
一. 背景 在刚接触开发的头几年里,说实话,根本不考虑多线程的这个问题,貌似那时候脑子里也有没有多线程的这个概念,所有的业务都是一个线程来处理,不考虑性能问题,当然也没有考虑多线程操作一条记录存在的并 ...
随机推荐
- 那么都数据库表,那么多不同记录。是怎样都存储在一个key-value数据库的?
那么都数据库表,那么多不同记录.是怎样都存储在一个key-value数据库的? :设置不同的键值而已!不同的表,选出统一的key规范 jedis.sadd("tom:friend:list& ...
- 【IOS笔记】Resource Management in View Controllers
Resource Management in View Controllers 视图控制器的资源管理 View controllers are an essential part of managin ...
- Web前端开发:什么是页面重回(repaints)与回流(reflow)
前言:什么是重绘与回流? 重绘(repaints)是一个元素外观的改变所触发的浏览器行为,例如改变vidibility.outline.背景色等属性.浏览器会根据元素的新属性重新绘制,使元素呈现新的外 ...
- javaWeb中struts开发——helloworld
1.新建一个web项目 2.选中project,右键,选择MyElcipse,选择add struts capab...添加struts支持,然后自己命名包 3.Struts在建立jsp时,标签要到 ...
- bower 基本应用
1.安装 npm install -g bower 2.指定下载目录: 在根目录建立文件 .bowerrc { "directory": "vendor/bower_d ...
- Linux下安装Xdebug
为了调试PHP程序,安装一下xdebug. 官方网址: http://www.xdebug.org 首先下载xdebug2.1.0,在官方首页下载源代码,下载回来的文件名是:xdebug-2.1.0. ...
- 【No.2 Ionic】Android打包
项目做完之后 接下来就是打包操作了,接下来直接说Android 打包操作 生成签名证书 keytool -genkey -alias vincentguo -keyalg RSA -validity ...
- Python之if语句
计算机之所以能做很多自动化的任务,因为它可以自己做条件判断. 比如,输入用户年龄,根据年龄打印不同的内容,在Python程序中,可以用if语句实现: age = 20 if age >= 18: ...
- nrf51822裸机教程-RTC
RTC0被协议栈使用了.所以在跑蓝牙程序的情况下.RTC0不能使用. RTC相关寄存器如下: EVTEN,EVTENSET,EVTENCLR. 这三个寄存器用来设置是否使能某个事件.(TICK,OVR ...
- 低功耗蓝牙4.0BLE编程-nrf51822开发(11)-蓝牙串口代码分析
代码实例:点击打开链接 实现的功能是从uart口发送数据至另一个蓝牙串口,或是从蓝牙读取数据通过uart打印出数据. int main(void) { // Initialize leds_init( ...