码迷,mamicode.com
首页 > 其他好文 > 详细

基于委托的异步编程实现

时间:2015-04-24 18:26:15      阅读:109      评论:0      收藏:0      [点我收藏+]

标签:

神麽是异步调用

在主线程中异步调用的方法不在主线程中执行,而是在另一个辅助线程中与主线程代码并行执行。给出一段示例代码:

当我们调用UploadPictureAsync方法时,图片尚未上传完成,我们就可以在控制台输出提示信息:“图片开始上传”。

/// <summary> /// 异步上传图片 /// </summary> /// <param name="fileLocalPath"></param> public void UploadPictureAsync(string id, string fileLocalPath) { DelegateMgr.UploadFileHandler del = new DelegateMgr.UploadFileHandler(UploadFile); del.BeginInvoke(id, fileLocalPath, delegate(IAsyncResult ar) { try { string fileUri = del.EndInvoke(ar); FileUploadEventArgs args = new FileUploadEventArgs(id, fileUri); if (PictureUploadCompleted != null) { PictureUploadCompleted(args); } } catch (Exception ex) { LogUtility.LogTableMessage("图片上传异常," + ex); } }, null);

Console.WriteLine("图片开始上传" ); } private string UploadFile(string id, string filePath) { string fileUri = string.Empty; try { WebClient wc = new WebClient(); string targetPath = "http://172.16.50.179:8090/FileUpload/ImageUpLoad.do"; byte[] bytes = wc.UploadFile(targetPath, "POST", filePath); fileUri = Encoding.Default.GetString(bytes);

Console.WriteLine("图片完成上传" ); } catch (Exception exception) { LogUtility.LogTableMessage("上传图片异常," + exception); } return fileUri; } public event Action<FileUploadEventArgs> PictureUploadCompleted;

编译器对委托都做了些神麽。。。

当我们定义一个委托时,编译器会为委托生成一个类。比如我们定义如下委托:

public delegate int DemoDelegate(int a, int b);

编译器会生成如下格式的类:

public sealed class DemoDelegate : MulticastDelegate
    {
        public DemoDelegate(object @object, IntPtr method)
        {
            //
        }

        public virtual int Invoke(int a, int b)
        {
            //方法体为空
        }

        public virtual IAsyncResult BeginInvoke(int a, int b, AsyncCallback callback, object asyncState)
        {
            //方法体为空
        }

        public virtual int EndInvoke(IAsyncResult ar)
        {
            //方法体为空
        }
    }
请注意,上面3个方法都是虚方法virtual,并且方法体都为空。

同步调用实现

class Program
    {
        static void Main(string[] args)
        {

            DemoDelegate del = new DemoDelegate(Add);

            //同步调用   Console.WriteLine("1 + 2 = " +  del(1, 2));

        }

        static int Add(int a, int b)
        {
            return a + b;
        }
    }

上面这种同步调用方式,实际上调用的是委托类的 Invoke 方法。

异步调用实现

基于委托的异步调用,实际上是通过 BeginInvoke 和 EndInvoke 两个方法来实现的。

我们先来分析一下BeginInvoke方法

public IAsyncResult BeginInvoke(

    <输入和输出变量>,

    AsyncCallback callback, object asyncState

)

<输入和输出变量>,表示委托声明中,参数有ref或者out修饰的。

callback,异步调用结束时自动回调的方法

asyncState,用于向callback方法提供参数信息,比如回调方法需要一些参数,asyncState 就可以用于填充这些参数。

对BeginInvoke方法的返回类型 IAsyncResult接口的说明

    [ComVisible(true)]
    public interface IAsyncResult
    {       
        object AsyncState { get; }
        WaitHandle AsyncWaitHandle { get; }
        bool CompletedSynchronously { get; }
        bool IsCompleted { get; }
    }

AsyncState,直接存储BeginInvoke方法中传入的 asyncState 参数值

AsyncWaitHandle,当异步操作完成时,该句柄处于 signaled 状态。

CompletedSynchronously,表示BeginInvoke是否同步调用完成。

IsCompleted,可以通过循环查询该属性判断异步操作是否完成。

 

接下来我们分析一下 EndInvoke 方法

public <方法返回值类型> EndInvoke(

    <声明为ref或out的参数>,

    IAsyncResult result)

调用 BeginInvoke方法会返回一个类型为 IAsyncResult 的对象,该对象会作为 EndInvoke方法的参数,这样EndInvoke方法不断轮询异步执行结果,发现异步调用完成时,会将异步调用结果作为返回值,如果异步调用方法有 ref 或者 out参数,也会负责填充这些参数。

调用者线程                         辅助线程

    |

    ①BeginInvoke     ------------------------>                          

    |                             ②异步调用方法执行

    ③EndInvoke      <-------------------------                         

 

基于委托的异步编程实现

标签:

原文地址:http://www.cnblogs.com/jiejie_peng/p/4453849.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!