http://www.cnblogs.com/panjun-Donet/archive/2009/03/03/1284700.html

让我们来看看同步异步的区别:

同步方法调用在程序继续执行之前需要等待同步方法执行完毕返回结果

异步方法则在被调用之后立即返回以便程序在被调用方法完成其任务的同时执行其它操作

.NET框架基类库中有好几种类都可以提供同步和异步的方法调用。

因为同步方法调用会导致程序流程中途等待,所以采用同步方法的情况下往往会导致程序执行的延迟

相比来说,在某些条件下选择异步方法调用就可能更好一些

例如,有的时候程序需要给多个Web服务发出请求,还有远程处理信道(HTTP、TCP)和代理,这时就最好采用异步方法

.NET Framework允许异步调用任何方法,定义与需要调用的方法具有相同签名的委托

CLR将自动为该委托定义添加适当签名的BeginInvoke虚方法和EndInvoke虚方法和Invoke方法。

关于委托的这3个方法的详细说明可以参考这文章
http://www.cnblogs.com/aierong/archive/2005/05/25/162181.html

我们先来了解这2个方法和一个委托和一个接口:

(1)

BeginInvoke方法用于启动异步调用

它与您需要异步执行的方法具有相同的参数,只不过还有两个额外的参数,将 AsyncCallback 和 AsyncState(可通过 IAsyncResult 接口的

AsyncState 属性获得)作为最后两个参数,如没有可以为空.

BeginInvoke立即返回,不等待异步调用完成。

BeginInvoke返回IasyncResult,可用于监视调用进度。

结果对象IAsyncResult是从开始操作返回的,并且可用于获取有关异步开始操作是否已完成的状态。

结果对象被传递到结束操作,该操作返回调用的最终返回值。

在开始操作中可以提供可选的回调。如果提供回调,在调用结束后,将调用该回调;并且回调中的代码可以调用结束操作。

(2)

EndInvoke方法用于检索异步调用结果。

在调用BeginInvoke后可随时调用EndInvoke方法,注意:始终在异步调用完成后调用EndInvoke.

如果异步调用未完成,EndInvoke将一直阻塞到异步调用完成。

EndInvoke的参数包括需要异步执行的方法的out和ref参数以及由BeginInvoke返回的IAsyncResult。

要注意的是,始终在异步调用完成后调用EndInvoke

(3)

AsyncCallback委托用于指定在开始操作完成后应被调用的方法

AsyncCallback委托被作为开始操作上的第二个到最后一个参数传递

代码原型如下:

[Serializable]

public delegate void AsyncCallback(IAsyncResult ar);

(4)

IAsyncResult接口

它表示异步操作的状态.

该接口定义了4个公用属性

下面写一个标准的例子


class Program

    {

        static void Main(string[] args)

        {

            number num = new number();

            sum numberadd = new sum(num.numberAdd);

            AsyncCallback numberback = new AsyncCallback(num.CallbackMethod2);

            numberadd.BeginInvoke(,,numberback,numberadd);

            Console.WriteLine("The sum is:");

            Console.WriteLine(num.m);

        }

    }

  //定义一个执行加法的委托
    public delegate int sum(int a, int b);

    public class number

    {

       ;

       //定义一个实现此委托签名的方法
       public int numberAdd(int a, int b)

       {

           int c = a + b;

           return c;

       }

       //定义一个与.net framework定义的AsyncCallback委托相对应的回调方法
       public  void CallbackMethod2(IAsyncResult ar2)

       {

           sum s = (sum)ar2.AsyncState;

           int number = s.EndInvoke(ar2);

           m = number;

          

       }

    }

实际上,发起和完成.NET异步调用有4种方案可供你选择

1.方案1-自己调用EndInvoke方法

异步执行方法的最简单方式是以BeginInvoke开始,对主线程执行一些操作,然后调用EndInvoke,EndInvoke直到异步调用完成后才返回

还是先来段自己喜欢的控制台代码:

 1using System;
 2
 3namespace ConsoleApplication1
 4{
 5    class Class1
 6    {
 7        public delegate void AsyncEventHandler();
 8
 9        void Event1()
10        {
11            Console.WriteLine("Event1 Start");
12            System.Threading.Thread.Sleep(2000);
13            Console.WriteLine("Event1 End");
14        }
15
16        void Event2()
17        {
18            Console.WriteLine("Event2 Start");
19            int i=1;
20            while(i<1000)
21            {
22                i=i+1;
23                Console.WriteLine("Event2 "+i.ToString());
24            }
25            Console.WriteLine("Event2 End");
26        }
27
28        void CallbackMethod(IAsyncResult ar) 
29        {
30            ((AsyncEventHandler) ar.AsyncState).EndInvoke(ar);
31        }
32
33
34        [STAThread]
35        static void Main(string[] args)
36        {
37            long start=0;
38            long end=0;
39            Class1 c = new Class1();
40            Console.WriteLine("ready");
41            start=DateTime.Now.Ticks;
42
43            AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
44            IAsyncResult ia=asy.BeginInvoke(null,null);
45            c.Event2();
46            asy.EndInvoke(ia);
47            
48            end =DateTime.Now.Ticks;
49            Console.WriteLine("时间刻度差="+ Convert.ToString(end-start) );
50            Console.ReadLine();
51        }
52    }
53}
54

此程序简单,异步的处理过程在代码43-46这几行
结果如下:


现在让我们来看看同步处理
修改代码43-46这几行代码:
c.Event1();
c.Event2();
结果如下:


前者的时间刻度大大小于后者
我们可以明显地看到异步运行的速度优越性

2.方案2-采用查询(IsCompleted属性)
IAsyncResult.IsCompleted属性获取异步操作是否已完成的指示,发现异步调用何时完成.
再次修改代码43-46这几行代码:
AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
IAsyncResult ia=asy.BeginInvoke(null,null);
c.Event2();
while(!ia.IsCompleted)
{
}
asy.EndInvoke(ia);

3.方案3-采用AsyncWaitHandle来等待方法调用的完成
IAsyncResult.AsyncWaitHandle属性获取用于等待异步操作完成的WaitHandle
WaitHandle.WaitOne方法阻塞当前线程,直到当前的WaitHandle收到信号
使用WaitHandle,则在异步调用完成之后,但在通过调用EndInvoke结果之前,可以执行其他处理
再次修改代码43-46这几行代码:
AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
IAsyncResult ia=asy.BeginInvoke(null,null);
c.Event2();
ia.AsyncWaitHandle.WaitOne();

4.方案4-利用回调函数(这个方法比较靠谱 见http://blog.csdn.net/onafioo/article/details/44356035)
如果启动异步调用的线程不需要处理调用结果,则可以在调用完成时执行回调方法
要使用回调方法,必须将代表该方法的AsyncCallback委托传递给BeginInvoke
再次修改代码43-46这几行代码:
AsyncEventHandler asy = new AsyncEventHandler(c.Event1);
asy.BeginInvoke(new AsyncCallback(c.CallbackMethod),asy);
c.Event2();

异步编程(AsyncCallback委托,IAsyncResult接口,BeginInvoke方法,EndInvoke方法的使用小总结)的更多相关文章

  1. 用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程

    让我们首先了解下什么时候用到C#异步调用: .NET Framework 允许您C#异步调用任何方法.定义与您需要调用的方法具有相同签名的委托:公共语言运行库将自动为该委托定义具有适当签名的Begin ...

  2. 【C#】用委托(Delegate)的BeginInvoke和EndInvoke方法操作线程

    让我们首先了解下什么时候用到C#异步调用: .NET Framework 允许您C#异步调用任何方法.定义与您需要调用的方法具有相同签名的委托:公共语言运行库将自动为该委托定义具有适当签名的Begin ...

  3. C#线程系列讲座(1):BeginInvoke和EndInvoke方法

    一.C#线程概述 在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能,将要执行的任务分解成多个子任务执行.这就需要在同一个进程中开启多个 ...

  4. delegate 中的BeginInvoke和EndInvoke方法

    开发语言:C#3.0 IDE:Visual Studio 2008 一.C#线程概述 在操作系统中一个进程至少要包含一个线程,然后,在某些时候需要在同一个进程中同时执行多项任务,或是为了提供程序的性能 ...

  5. 转:C#线程系列讲座(1) BeginInvoke和EndInvoke方法

    转载自:http://www.cnblogs.com/levin9/articles/2319248.html 开发语言:C#3.0IDE:Visual Studio 2008本系列教程主要包括如下内 ...

  6. 黄聪:C#多线程教程(1):BeginInvoke和EndInvoke方法,解决主线程延时Thread.sleep柱塞问题(转)

    开发语言:C#3.0 IDE:Visual Studio 2008 本系列教程主要包括如下内容: 1.  BeginInvoke和EndInvoke方法 2.  Thread类 3. 线程池 4. 线 ...

  7. C# BeginInvoke和EndInvoke方法

    转载自:BeginInvoke和EndInvoke方法 IDE:Visual Studio 2008 本系列教程主要包括如下内容:1. BeginInvoke和EndInvoke方法 2. Threa ...

  8. BeginInvoke和EndInvoke方法

    本系列教程主要包括如下内容:1. BeginInvoke和EndInvoke方法 2. Thread类 3. 线程池 4. 线程同步基础 5. 死锁 6. 线程同步的7种方法 7. 如何在线程中访问G ...

  9. 委托的BeginInvoke和EndInvoke方法

    .NET Framework 允许异步调用任何方法,为了实现异步调用目标,需要定义与被调用方法具有相同签名的委托.公共语言运行时会自动使用适当的签名为该委托定义 BeginInvoke 和 EndIn ...

随机推荐

  1. apktool + eclipse 动态调试APK

    用了会AndBug,尽管挺强大的可是作为习惯了OD.EDB作为动态调试工具的人,自然有些不习惯,于是乎寻求新的动态调试解决方式.但大多数都是NetBeans + apktool.想着还得多下一个IDE ...

  2. 九度OJ 1128:求平均年龄 (基础题)

    时间限制:1 秒 内存限制:32 兆 特殊判题:否 提交:2080 解决:1084 题目描述: 班上有学生若干名,给出每名学生的年龄(整数),求班上所有学生的平均年龄,保留到小数点后两位. 输入: 第 ...

  3. r testifying that your code will behave as you intend.

    https://github.com/stretchr/testify Testify - Thou Shalt Write Tests    Go code (golang) set of pack ...

  4. JS中正则匹配开头不带空格,结尾也不带空格的字符串

    在做项目的时候,要求限制SSID的长度.以及开头和结尾不能是空格. var reg = /^\S.{0,30}\S$/ "$$$  $$".match(reg);   ==> ...

  5. zabbix数据库创建初始化

    MariaDB [(none)]> create database zabbix character set utf8; MariaDB [(none)]> grant all privi ...

  6. codeforces C. Team 解题报告

    题目链接:http://codeforces.com/problemset/problem/401/C 题目意思:给出0和1的数目(分别为n和m个),问是否能构造一条同时满足连续两个0不能再一起和连续 ...

  7. Jmeter参数化_CSV Data Set Config

    1. 在用函数助手进行参数化的时候遇到一个问题,每个线程组每次循环的时候读取的值都是一样的,为了解决这个问题,将函数助手替换为CSV_Data_Set_Config. 2. 添加配置元件csv dat ...

  8. the art of seo(chapter one)

    preface:Andy Johns (@ibringtraffic):growth strategist@Wealthfront ***1.Search Reflecting Consciousne ...

  9. UniCode转码

    <script type="text/javascript"> var GB2312UnicodeConverter = { ToUnicode: function ( ...

  10. IDEA 设置背景颜色及字号

    intellij IDEA 设置背景颜色   File--> Settings 2. Appearance & Behavior --> Appearance 设置边框背景颜色 3 ...