• 基于委托的异步编程实现


    神麽是异步调用

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

    当我们调用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      <-------------------------                         

     

  • 相关阅读:
    【java开发需要的环境资源以及开发工具】慢慢更新
    【如何编写有质量代码】【转】
    base——JavaSE&&JavaEE&&JavaME的区别【Java中常用的包结构】
    Mysqlsql——And【sql语句之为何用and一个字段两个值得不到表中的数据】
    Struts2——执行流程
    base——本地资源路径&&网络资源路径&&正反斜杠在Java中的用法
    base——new File(String Path)加载资源问题
    2019-06-11_Python中文编码
    2019-06-11-Python简介
    2019-06-05 org.apache.ibatis.binding.BindingException: Invalid bound statement (not found): com.taotao.search.mapper.SearchItemMapper.getItemList
  • 原文地址:https://www.cnblogs.com/jiejie_peng/p/4453849.html
Copyright © 2020-2023  润新知