`
fdyang
  • 浏览: 79671 次
  • 性别: Icon_minigender_1
  • 来自: 苏州
社区版块
存档分类
最新评论

(C#)异步编程(进程,线程,计时器)

阅读更多

(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
- 包含很多成员,可以通过属性和方法来操作计时器。
- 这个计时器可以运行在用户接口线程或工作者线程上。


       

 


 

 

分享到:
评论

相关推荐

    C# 多线程计时器,倒计时

    C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时 C# 多线程 计时器 到计时

    C#异步编程方式以及示例

    这是我自己写的C#异步编程方式以及简单示例: 包含委托、task、await async 方式来实现异步。

    C#异步编程概述

    Windows 应用程序编程中常见的一个模式就是,在GUI用户界面下,将耗时的文件和网络处理放入 子线程,以避免用户界面不能响应的问题。在.NET出现以前,创建线 程并监视线程结束,还要更新 界面等工作,即复杂又要手写...

    C#异步编程官网手册[收集].pdf

    C#异步编程官网手册[收集].pdf

    基于c#的简单的进程与线程管理器

    基于c# 简单的 进程 线程 管理器 适合于新手用

    C# 5.0异步编程

    C# 5.0 异步编程技术,关注C#新的异步编程特性。

    C# TCP异步收发信息 多线程

    C#语言,运用TCP异步收发信息。客户端只要知道服务器端IP和端口号,就可以和服务器建立连接,异步收发信息。本实例包括服务器端和客户端程序,并且有很详细的注释,希望大家看后能有一定的收获。

    c#Winform异步线程刷新UI

    使用开发工具为VS2013;.net:4.0 多线程异步刷新ui界面,实时获取任务进度并进行反馈。

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

    主要讲述的是C#中异步和多线程的区别,对于过了C#开发的初级阶段的开发者,是个不错的学习文档,希望对你有帮助。

    c#多线程线程池和异步编程

    我们将在这里进一步讨论一些.NET类,以及他们在多线程编程中扮演的角色和怎么编程。它们是:  System.Threading.ThreadPool 类  System.Threading.Timer 类  如果线程的数目并不是很多,而且你想控制每个线程的...

    c#线程同步与异步编程

    通过实例说明c#中同步和异步的区别,适合于初学者,能够帮助理解同步和异步的概念。

    C#Winform异步多线程和线程池集成的用法

    本程序详细介绍了线程和线程池的用法,使用多线程进行和异步编程实现数据库操作和日志的记录

    C# 获取当前所有进程线程CUP占用率

    监控系统所有进程的CPU使用情况 显示CPU占用大于0的进程,定时刷新 可以查看当前系统运行的各进程cpu占用率 在CSDN上找到两个都不太好用,自己写了一个VS...用途:查看自己写的程序那个线程运行时间最多,耗资源等。

    异步编程_C#_异步编程_

    学习C#异步编程技巧和实现原理,提升异步编程的质量

    C# Socket 同步异步编程实例

    .net dotnet C# Socket 同步,异步 编程实例

    C#多线程编程实战 源代码

    本书是一本通俗易懂的C#多线程编程指南,通过70多个容易理解的示例,循序渐进地讲解C#5.0中的异步及并发编程,引导读者了解Windows下C#多线程编程的多样性。 通过阅读本书,你将学到: 使用原始线程、异步线程,...

    C#异步编程详解

    前言 本节主要介绍异步编程中Task、Async和Await的基础知识。...C#5.0 .NET4.5 以后关键字Async和Await的使用,使得异步编程变得异常简单。 多线程中的处理程序依然是顺序执行,但是多线程的缺点也同样明显,

    C#多线程编程实例实战.doc

    C#多线程编程实例实战.doc

    C#通讯 Socket异步编程源代码与资料

    Socket异步编程源代码与资料 Socket C#通讯

    C# 多线程异步下载

    利用C# WentClient异步编程的网络开发,多线程同时下载,资源附件是源码,VS2010开发的,使用于对网络学习编程,以及多线程运用的童鞋可以参考。

Global site tag (gtag.js) - Google Analytics