- 浏览: 79671 次
- 性别:
- 来自: 苏州
文章分类
最新评论
(C#)异步编程(进程,线程,计时器)
- 博客分类:
- C#/.NET
(C#)异步编程(进程,线程,计时器)
进程
- 启动一个程序时,系统在内存中创建了一个新的进程(process).
- 进程就是一组资源,他们构成了一个正在运行的程序。这些资源包括虚拟地址空间,文件句柄以及程序启动需要的其他东西载体。
线程
- 在进程中,系统创建了一个叫做线程(thread)的内核对象,线程体现了一个程序的真实执行情况。
- 程序开始运行时,系统在线程中开始执行Main方法的第一条语句。
- 线程时由系统负责调度的处理器(不是进程)上的执行单位.
同步编程
- 程序只有一个线程,从程序的第一行语句到最后一行语句顺序执行。
异步编程
- 程序发起多个线程,理论上是同一时间执行。(实际上,不是完全真的在同一时间执行,处理器会按照时间片轮流执行)
多线程处理
- 在程序中使用多个线程叫做多线程处理。增加了程序的负荷和额外的复杂度。
- 为了帮我们降低创建和销毁线程相关的成本,CLR为每一个进程维护了一个线程池(thread pool). 一开始进程的线程时空的,如果进
程使用的线程被创建,并且完成了线程的执行,它不会被销毁,而是加入到进程的线程池中。之后,如果进程需要另外一个线程,CLR会
从池中还原一个线程,就节省了很多时间。
- 多线程处理对GUI编程非常重要,保持良好的用户体验。
异步编程模式
- C#有个简单易用的机制用于异步执行方法,那就是使用委托。
- 如果委托对象在调用列表中只有一个方法,它就可以异步执行这个方法。
- 委托类有两个方法,叫做BeginInvoke 和 EndInvoke
* 使用方法如下:
当调用委托的BeginInvoke方法是,它开始在线程中的独立线程上执行引用方法,并且立即返回原始线程。原始线程可以继续,而引用
方法会在线程池中并行执行。
当程序希望获取已完成的异步方法的结果时,可以检查BeginInvoker返回的IAsyncResult的IsCompleted 属性,或调用委托的
EndInvoke方法来等待委托完成.
- 异步方法调用的3种标准模式.
(1)等待-直到完成(wait-until-done).
-> 在发起了异步方法以及做了一些其他处理之后,原始线程就中断并且等异步方法完成之后再继续。
(2)轮询(polling)
-> 原始线程定期检查发起的线程是否完成,如果没有则可以继续做一些其他的事情.
(3)回调(callback)
-> 原始线程一直执行,无需等待或检查发起的线程是否完成。
BeginInvoke 和 EndInvoke
- BeginInvoke 从线程池中获取一个线程并且在新的线程开始时运行引用方法。
- BeginInvoke 返回给调用线程一个实现IAsyncResult接口的对象,这个接口引用包含了异步方法的当前状态,原始线程然后可以继续
执行。
delegate long MyDel( int first, int second); //声明委托
...
static long Sum(int x, int y) { ...} //定义方法来匹配委托。
...
MyDel del = new MyDel(Sum); //创建委托对象.
//调用委托对象的BeginInvoke方法并且提供了参数3,5, callback(设null), state (设null) .
IAsyncResult iar = del.BeginInvoke (3,5,null,null);
EndInvoke 方法用来获取由异步方法调用返回的值,并且释放线程使用的资源。
long result = del.EndInvoke(iar);
EndInvoke 提供了从异步方法调用的所有输出,包括ref 和out 参数. 如果委托的引用方法有ref 或out 参数, 他们必须包含在
EndInvoke 的参数列表中.
long result = del.EndInvoke(out someInt, iar);
等待-直到-结束(wait-untill-done)模式
- 原始线程发起一个异步方法的调用,做一些其他的处理,然后停止并等待,一直到线程结束。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //声明委托 delegate long MyDel(int first, int second); namespace ConsoleApplication1 { class Program { static long Sum(int x, int y) //声明方法匹配委托,用于异步执行。 { Console.WriteLine(" Inside Sum"); Thread.Sleep(3000); return (x + y); } static void Main() { MyDel del = new MyDel(Sum); Console.WriteLine("Before BeginInvoke"); IAsyncResult iar = del.BeginInvoke(3, 5, null, null); // 开始异步调用 Console.WriteLine("After BreginInvoke"); Console.WriteLine("Doing stuff"); long result = del.EndInvoke(iar); //等待结束并获取结果 Console.WriteLine("After EndInvoke:{0}", result); } } }
输出:
Before BeginInvoke
After BeginInvoke
Doing stuff
Inside Sum
After EndInvoke: 8 //等待3秒后,显示结果.
轮询(polling)模式
-原始线程发起了异步方法的调用,做一些其他事情,然后用IAsyncResult对象的IsComplete属性来定期检查开启的线程是否完成。如果
异步方法已经完成,原始线程就调用EndInvoke 并继续。否则,做一些其他的处理,然后再来定期检查。
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; //声明委托 delegate long MyDel(int first, int second); namespace ConsoleApplication1 { class Program { static long Sum(int x, int y) //声明方法匹配委托,用于异步执行。 { Console.WriteLine(" Inside Sum"); Thread.Sleep(5000); return (x + y); } static void Main() { MyDel del = new MyDel(Sum); Console.WriteLine("Before BeginInvoke"); IAsyncResult iar = del.BeginInvoke(3, 5, null, null); // 开始异步调用 Console.WriteLine("After BreginInvoke"); //检查异步方法是否完成 while (!iar.IsCompleted) { Console.WriteLine("Not done, wait for 1 more second."); //处理一些其他事情 Thread.Sleep(1000); } Console.WriteLine("Done"); long result = del.EndInvoke(iar); //等待结束并获取结果 Console.WriteLine("After EndInvoke:{0}", result); } } }
输出:
Before BeginInvoke
After BeginInvoke
Not done, wait for 1 more second.
Inside Sum
Not done, wait for 1 more second.
Not done, wait for 1 more second.
Not done, wait for 1 more second.
Not done, wait for 1 more second.
Done
After EndInvoke:8
回调(callback)模式
-一旦初始线程发起了异步方法,就自己管自己,不再考虑同步。当异步方法调用结束后,系统调用一个用户自定义的方法来处理结果,
并且调用委托的EndInvoke 方法.
-BeginInvoke的参数列表中个最后的两个额外参数被回调方法用作:
第一个参数,callback,是回调方法的名字.
第二个参数,state,可以使null 或者传入回调方法的一个对象的引用。通过IAsyncResult参数的AsyncState属性来获取这个对象,参
数的类型是object.
回调方法
void asyncCallback(IAsyncResult iar)
IAsyncResult iar1=del.BeginInvoke(3,5,new AsyncCallback(CallWhenDone),null);
或 IAsyncResult iar1=del.BeginInvoke(3,5,CallWhenDone,null);
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; using System.Runtime.Remoting.Messaging; //调用AsyncResult类型. //声明委托 delegate long MyDel(int first, int second); namespace ConsoleApplication1 { class Program { static long Sum(int x, int y) //声明方法匹配委托,用于异步执行。 { Console.WriteLine(" Inside Sum"); Thread.Sleep(500); //备注A return (x + y); } static void CallWhenDone(IAsyncResult iar) { Console.WriteLine(" Insdie CallWhenDone."); AsyncResult ar = (AsyncResult)iar; MyDel del = (MyDel)ar.AsyncDelegate; long result = del.EndInvoke(iar); Console.WriteLine(" The result is : {0}", result); } static void Main() { MyDel del = new MyDel(Sum); Console.WriteLine("Before BeginInvoke"); IAsyncResult iar = del.BeginInvoke(3, 5, new AsyncCallback(CallWhenDone), null); // 开始异步调用 Console.WriteLine("Doing more work in main,ie. wait for 1 more second."); Thread.Sleep(1000); Console.WriteLine("Done with Main."); } } }
输出:
Before BeginInvoke
Doing more work in main, ie. wait for 1 more second.
Inside Sum
Inside CallWhenDone.
The result is : 8
Done with Main.
备注A: 如果将此处修改为: Thread.Sleep(5000);
则输出:
Before BeginInvoke
Doing more work in main, ie. wait for 1 more second.
Inside Sum
Done with Main.
计时器
- 计时器在每次时间到期之后调用回调方法。回调放必须是TimerCallback委托形式的.
void TimerCallback(object state)
- 当计时器到期后,系统会从线程池中的线程上开启一个回调方法,提供state对象作为其参数,并且开始运行.
- 可以设置的计时器的一些特性如下:
dueTime:是回调方法首次被调用之前的时间。如果dueTime被设置为特殊的值Timeout Infinite ,则计时器不会开始。如果被设置为0,
回调函数会被立即调用.
period 是两次成功调用回调函数之间的时间间隔。如果它的值设置为Timeout.Infinite,回调在首次被调用之后不会再被调用.
state 可以使null 或在每次回调方法执行时要传入的对象的引用。
Timer类的最为常用的构造函数如下:
Timer(TimerCallback callback, object state, uint dueTime, uint period)
创建Timer对象的一个实例:
//MyCallback是回调的名字,someObject是传给回调的对象, 2000毫秒后第一次调用,以后每隔1000毫秒调用一次.
Timer myTimer = new Timer( MyCallback, someObject, 2000, 1000 ) ;
Timer对象被创建后,我们还可以使用Change方法来改变 dueTime 或 period.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading; namespace ConsoleApplication1 { class Program { int TimesCalled = 0; void Display(Object state) { Console.WriteLine("{0} {1}", (string)state, ++TimesCalled); } static void Main() { Program p = new Program(); Timer myTimer = new Timer(p.Display, "Processing timer event", 2000, 1000); Console.WriteLine("Timer Start."); Console.ReadLine(); } } }
输出:
Timer Start.
Processing timer event 1
Processing timer event 2
Processing timer event 3
Processing timer event 4
Processing timer event 5
Processing timer event 6
...
(每隔一秒会增加一行输出 )
.NET BCL 还提供了其他几个计时器类.
System.Windows.Forms.Timer -> 主要用于GUI编程.
- 这个类在Windows应用程序中使用,可以定期把WM_TIMER消息放到程序的消息队列中.
- 当程序从队列获取消息后,它会在主用户接口线程中异步处理。
System.Timers.Timer
- 包含很多成员,可以通过属性和方法来操作计时器。
- 这个计时器可以运行在用户接口线程或工作者线程上。
发表评论
-
(WCF) 示例1:Magic Eight Ball.
2013-01-13 17:31 807实例一: 构建一个简 ... -
(WF) 基础1.创建一个WF4.0项目
2012-12-31 16:52 1068(WF) 基础1.创建一个WF4.0项目。 从WinF ... -
(WCF) 基础知识
2012-12-29 14:07 800SOA(Service-Oriented ... -
Visual Studio “类视图”和“对象浏览器”图标
2012-12-29 12:52 881转载: http://blog.sina.com.cn/s/b ... -
WCF的编程模型-实例: 构建一个简单的WCF应用.
2012-12-28 14:45 3171WCF的编程模型-实例: 构 ... -
(C#)属性(property)
2012-12-25 22:39 787(C#)属性(property) 属性是字段和方法的一个交集 ... -
(C#)事件(Event)
2012-12-20 22:06 1073(C#)事件(Event) 事件好像是被简化的针 ... -
(C#)接口(Interface)
2012-12-11 15:04 916(C#)接口(Interface)接口是 ... -
(C#)委托(delegate)
2012-12-11 11:42 679(C#)委托(delegate)委托是包含具有相同签名和返回值 ... -
(C#)枚举.
2012-12-11 10:32 636(C#)枚举. 枚举是由程序员定义的类型。- 与结构一样,枚 ... -
(C#)异常及处理.
2012-12-11 09:42 587(C#)异常及处理. 异常时程序运行时发生的错误,它违反了一 ... -
C # 基本概念 (面试题)
2012-11-22 10:37 827Interview Problem 1.Does C# s ... -
C sharp 基本概念(面试题)
2012-11-22 10:35 0Interview Problem 1.Does C# ... -
C# 基本概念(问题)
2012-11-22 10:11 1123传入某个属性的set方 ...
相关推荐
C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时
这是我自己写的C#异步编程方式以及简单示例: 包含委托、task、await async 方式来实现异步。
Windows 应用程序编程中常见的一个模式就是,在GUI用户界面下,将耗时的文件和网络处理放入 子线程,以避免用户界面不能响应的问题。在.NET出现以前,创建线 程并监视线程结束,还要更新 界面等工作,即复杂又要手写...
C#异步编程官网手册[收集].pdf
基于c# 简单的 进程 线程 管理器 适合于新手用
C# 5.0 异步编程技术,关注C#新的异步编程特性。
C#语言,运用TCP异步收发信息。客户端只要知道服务器端IP和端口号,就可以和服务器建立连接,异步收发信息。本实例包括服务器端和客户端程序,并且有很详细的注释,希望大家看后能有一定的收获。
使用开发工具为VS2013;.net:4.0 多线程异步刷新ui界面,实时获取任务进度并进行反馈。
主要讲述的是C#中异步和多线程的区别,对于过了C#开发的初级阶段的开发者,是个不错的学习文档,希望对你有帮助。
我们将在这里进一步讨论一些.NET类,以及他们在多线程编程中扮演的角色和怎么编程。它们是: System.Threading.ThreadPool 类 System.Threading.Timer 类 如果线程的数目并不是很多,而且你想控制每个线程的...
通过实例说明c#中同步和异步的区别,适合于初学者,能够帮助理解同步和异步的概念。
本程序详细介绍了线程和线程池的用法,使用多线程进行和异步编程实现数据库操作和日志的记录
监控系统所有进程的CPU使用情况 显示CPU占用大于0的进程,定时刷新 可以查看当前系统运行的各进程cpu占用率 在CSDN上找到两个都不太好用,自己写了一个VS...用途:查看自己写的程序那个线程运行时间最多,耗资源等。
学习C#异步编程技巧和实现原理,提升异步编程的质量
.net dotnet C# Socket 同步,异步 编程实例
本书是一本通俗易懂的C#多线程编程指南,通过70多个容易理解的示例,循序渐进地讲解C#5.0中的异步及并发编程,引导读者了解Windows下C#多线程编程的多样性。 通过阅读本书,你将学到: 使用原始线程、异步线程,...
前言 本节主要介绍异步编程中Task、Async和Await的基础知识。...C#5.0 .NET4.5 以后关键字Async和Await的使用,使得异步编程变得异常简单。 多线程中的处理程序依然是顺序执行,但是多线程的缺点也同样明显,
C#多线程编程实例实战.doc
Socket异步编程源代码与资料 Socket C#通讯
利用C# WentClient异步编程的网络开发,多线程同时下载,资源附件是源码,VS2010开发的,使用于对网络学习编程,以及多线程运用的童鞋可以参考。