`
yzd
  • 浏览: 1858535 次
  • 性别: Icon_minigender_2
  • 来自: 北京
文章分类
社区版块
存档分类
最新评论

异步委托,恰似一江春水向东流(你了解的异步委托)

 
阅读更多

书是书,你是你,照抄文字那是书本的东西,你必须有你自己理解,就算是 有错误的认识。下面说下异步委托,个人涉 .net不深,经验尚浅,如果说的不对,希望大家指出来。
    对于线程,我不想多说了,可以搜索博客园 风尘浪子的  "线程上与线程下",说的相当详细。本篇博文就是针对:了解一些线程但对异步委托又模糊的朋友。
其实这个异步委托,应该结合 线程Thread来一起讨论的,为什么我们现在对这个异步委托爱不释手,是因为它的3个原因:
.不影响主线程的执行
.合理的利用ThreadPool线程池的线程
.异步委托本质是调用了线程池的工作者线程,不需要为了新建和注销线程烦恼,统一由线程池管理。

1.传统的同步委托(模拟委托的方法执行时间很长)
模拟委托的方法执行很长: Thread.Sleep(TimeSpan.FromSeconds(3));

View Code
//声明委托
    public delegate void DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            delemethod("Mr.w");
            Console.WriteLine("下面我还要执行方法....");
            
        }

        //要被委托调用的方法
        static void Speaking(string name)
        {
            Console.WriteLine("我的名字是:{0}",name);
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("委托方法执行完毕!");
        }



分析:
.按F11大家都可以自己分析了,Main()是所有程序的开始,该程序调用Speaking()方法会休眠3秒,这样影响了主线程的下面的方法执行时间。
.从头到尾,程序都只有一个线程,思考下:可不可以在利用一个子线程去帮我执行我的委托方法,不影响我的主线。
答案是:可以,对于这种情况,我们可以 新建Thread类的线程,或者利用异步委托(线程池的工作者线程),这里我们不适用新建的线程,因为它不便于管理。

2.初始异步委托

View Code
//声明委托
    public delegate void DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //执行异步委托
            delemethod.BeginInvoke("Mr.w",null,null);
            //主线程方法
            Console.WriteLine("下面我还要执行方法....");
            
        }

        //要被委托调用的方法
        static void Speaking(string name)
        {
            Console.WriteLine("我的名字是:{0}",name);
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("委托方法执行完毕!");
        }
    }

 

输出:
下面我还要执行方法....
我的名字是:Mr.w
复制代码




分析:
1.怎么回事?怎么好像 委托方法没有执行完毕?
答:线程分为:前台线程和后台线程,默认线程池的都是后台线程,主线程是不会管 后台线程是否执行完毕,就直接退出程序。新建的Thread类的线程默认是前台线程,主线程必须等待他执行完毕再退出AppDomain.
是否是前台或者后台线程取决于:IsBackground属性。
2.我们利用一个Console.ReadKey();可以让主线程不退出AppDomain。


3.说一说带返回值的异步委托
大家都知道,有时候,主线程根本就不关心 委托方法的返回值,所以是否能把 异步委托的返回值 显示在我的主窗口就更不关心了,但是返回值 也是可以解决很多问题的:
1.上篇博文已经提及了,非void委托方法可以返回  异常信息
2.有些软件需要 把委托方法的返回值 作为另一个方法的参数来处理

代码1:
 

View Code
//声明委托
    public delegate string DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //执行异步委托
           IAsyncResult result=delemethod.BeginInvoke("Mr.w",null,null);
           string s=delemethod.EndInvoke(result);
            //主线程方法
            Console.WriteLine("下面我还要执行方法....");
            //阻止主线程退出程序
            Console.ReadKey();
        }

        //要被委托调用的方法
        static string Speaking(string name)
        {
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("我的名字是:{0}", name);
            return "委托方法执行完毕!";
        }
    }
输出:
我的名字是:Mr.w
下面我还要执行方法....
复制代码



注意:
看输出的结果,按照我们的理论,应该输出结果是:

下面我还要执行方法....
我的名字是:Mr.w
复制代码

 

怎么结果相反了?
答案:
1.因为异步委托  由 BeginInvoke()方法开始,以EndInvoke()结束。
2.异步委托的返回值是由 EndInvoke();返回的。

所以:你如果想要返回值,必须写EndInvoke();,可是有人要问了,如果在主线程调用EndInvoke()方法,主线程不是要等待 子线程执行完毕之后才 会执行下面的代码,这和  同步执行有什么区别?那异步就没有意义了。

正确!完全正确,但是有没有 又可以得到异步委托的结果,又不影响主线程的方式。

4.说一说 得到返回值,又不影响主线程的方式

解决这个问题,必须了解下,异步委托的BeginInvoke()方法

1.BeginInvoke()最容易被忘记的是:执行BeginInvoke()方法的委托变量,如上面的:delemethod变量必须是单播委托,也就是说只能绑定一个方法。对于多播委托,请把所有方法遍历出来在使用异步委托,如何遍历查询我的上一篇博文。
2.BeginInvoke()方法有4个参数,前2个是和你的委托方法的参数一致的,后2个参数,分别是AsyncCallback类型和Object类型,其中AsyncCallback是一个委托类型,它用于当异步执行完毕时自动进行调用的方法,最后一个参数Object类型可以通过 AsyncResult类型变量的AsyncState属性获得,或者 IAsyncResult类型变量的AsyncState属性
3.BeginInvoke()方法 返回值是 一个IAsyncResult接口,实质就是AsyncResult的对象。通过AsyncResult的AsyncDelegate获得delemthod委托对象,然后再在其上调用EndInvoke()方法。

是不是越来越迷糊,结合案例看:
代码1:

View Code
//声明委托
    public delegate string DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //声明回调函数
            AsyncCallback callback = new AsyncCallback(CallBack);
            //执行异步委托
            
            delemethod.BeginInvoke("Mr.w",callback,delemethod);
           
            //主线程方法
            Console.WriteLine("下面我还要执行方法....");
            //阻止主线程退出程序
            Console.ReadKey();
        }
        //回调方法
        static void CallBack(IAsyncResult ar)
        {
            DeleMethod delemethod = (DeleMethod)ar.AsyncState;//BeginInvoke()方法返回的对象的属性AsyncState,就是BeginInvoke()方法最后一个Object参数
            string s = delemethod.EndInvoke(ar);
            Console.WriteLine(s);
        }
        //要被委托调用的方法
        static string Speaking(string name)
        {
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("我的名字是:{0}", name);
            return "委托方法执行完毕!";
        }
    }
输出:
下面我还要执行方法....
我的名字是:Mr.w
委托方法执行完毕!
复制代码



先看结果:结果是符合我们的理论的。
分析:
1.大家都知道异步委托要想有返回值,必须调用EndInvoke()方法,但是用哪个委托变量调用呢?
.BeginInvoke()方法最后一个参数就是 BeginInvoke()返回值的IAsyncResult类型变量的AsyncState,这样获取委托变量的对象,如代码1
.或者通过AsyncResult的AsyncDelegate获得delemethod委托对象,然后再在其上调用EndInvoke()方法。如代码2
代码2:
 

View Code
//声明委托
    public delegate string DeleMethod(string name);
    class Program
    {
        static void Main(string[] args)
        {
            DeleMethod delemethod = Speaking;
            //声明回调函数
            AsyncCallback callback = new AsyncCallback(CallBack);
            //执行异步委托
            
            delemethod.BeginInvoke("Mr.w",callback,null);
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            //主线程方法
            Console.WriteLine("下面我还要执行方法....");
          
            //阻止主线程退出程序
            Console.ReadKey();
        }
        //回调方法
        static void CallBack(IAsyncResult ar)
        {
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            AsyncResult result = (AsyncResult)ar;
            DeleMethod delemethod = (DeleMethod)result.AsyncDelegate;//通过AsyncResult的AsyncDelegate获得delemethod委托对象
            string s = delemethod.EndInvoke(ar);
            Console.WriteLine(s);
            Console.WriteLine("当前线程ID:"+Thread.CurrentThread.ManagedThreadId.ToString());
        }
        //要被委托调用的方法
        static string Speaking(string name)
        {
           
            //利用休眠3秒钟,模拟委托执行的方法很长
            Thread.Sleep(TimeSpan.FromSeconds(3));
            Console.WriteLine("当前线程ID:" + Thread.CurrentThread.ManagedThreadId.ToString());
            Console.WriteLine("我的名字是:{0}", name);
            return "委托方法执行完毕!";
        }
    }
输出:
当前线程ID:1
下面我还要执行方法....
当前线程ID:3
我的名字是:Mr.w
当前线程ID:3
委托方法执行完毕!
当前线程ID:3
0
1
分享到:
评论

相关推荐

    控件句柄异步委托.rar

    而异步委托则是对异步编程模型的支持,它允许你在不阻塞主线程的情况下执行耗时的操作。在Windows Forms或WPF应用中,如果你需要在后台执行一项任务,比如网络请求或数据库操作,可以使用BeginInvoke或AsyncCallback...

    【VB.NET】多线程加异步委托实现背景透明的等待窗体(loading界面),超时可以取消操作

    为了给用户提供更好的体验,读取数据库等程序需要长时间来执行的操作,需要弹出一个等待界面。可以一边执行需要等待的操作,一边...本资源使用VS2017软件,VB.NET编程,异步委托和多线程编程实现背景透明的等待窗体。

    C#中定时器的是使用及异步委托

    在C#编程中,定时器(Timer)是一个非常重要的组件,它允许我们在特定的时间间隔内执行某些任务。这里我们将深入探讨C#中的...在实际项目中,你需要根据具体需求选择合适的定时器类型,并灵活运用异步委托来优化性能。

    c#委托事件异步例子

    在C#编程中,委托和事件是两种非常重要的特性,它们是实现面向对象设计的关键工具,尤其是对于构建异步应用程序。下面将详细讲解这两个概念及其在异步编程中的应用。 一、委托 委托在C#中可以被视为一种类型,它...

    C#用委托BeginInvoke做异步线程

    C#用委托BeginInvoke做异步线程 在C#中,异步线程是一个非常重要的概念,通过使用委托的BeginInvoke方法,可以实现异步线程的执行。在本文中,我们将详细介绍如何使用委托的BeginInvoke方法来实现异步线程,以及...

    线程-异步事件委托

    通过这种方式,你可以利用VB2008中的异步事件委托来构建高效的多线程应用程序。这种技术尤其适用于处理I/O密集型任务,如网络通信、文件读写等,以及需要长时间运行的操作,因为它们不会阻塞主线程,从而保持程序的...

    带返回值的异步委托和lambada结合

    异步委托与Lambda表达式的结合使用,能够让我们在不阻塞主线程的情况下执行耗时操作,同时还能优雅地处理返回值。本文将深入探讨如何在UI操作和线程间有效使用这种组合。 首先,异步委托是一种能够启动异步操作的...

    委托实现socket 异步传输

    首先,让我们了解委托的概念。委托在C#中类似于函数指针,它可以引用一个或多个具有相同签名的方法。在异步操作中,委托扮演了回调函数的角色,当异步操作完成时,通过委托调用指定的方法,通知应用程序结果。 在...

    C# Socket异步通信+事件与委托+通信程序与界面分离

    本教程主要探讨如何使用C#的Socket实现异步通信,并结合事件和委托来处理通信过程中的消息传递,以及如何将通信逻辑与用户界面(UI)分离,以实现更高效、更灵活的程序设计。 首先,让我们理解什么是Socket异步通信。...

    委托异步调用的简单例子(一看就明白,你懂的)

    本篇将通过一个简单的委托异步调用的例子,帮助你深入理解这一概念。 委托在.NET中是一种类型安全的回调机制,它允许我们将方法作为参数传递给其他方法。异步委托则是进一步扩展了这一特性,使我们能够启动一个异步...

    c# socket tcp 多线程 异步聊天 委托 服务 客户端

    本项目"c# socket tcp 多线程 异步聊天 委托 服务 客户端"聚焦于C#语言实现TCP协议的Socket通信,结合多线程和异步编程,以及委托的概念,构建了一个高效的聊天应用实例。以下将详细介绍这些知识点。 首先,Socket...

    c# 使用UDPClient实现异步通信的两种表现形式

    本篇将详细介绍如何使用UDPClient实现异步通信的两种表现形式:一种是通过委托,另一种是不使用委托。 首先,让我们来看看使用委托的方式。在C#中,委托是一种类型,它可以引用方法。在异步操作中,委托作为回调...

    Socket+多线程+异步委托实现文件传输

    "Socket+多线程+异步委托实现文件传输"这个主题聚焦于如何高效地在多个客户端和服务器之间进行文件交换。让我们深入探讨一下这个话题涉及的关键技术。 1. **Socket**:Socket是网络编程的基本组件,它提供了应用...

    .Net的异步机制(委托Delegate)

    在异步编程中,委托允许我们使用BeginInvoke和EndInvoke方法启动异步调用。下面我们将深入探讨这两个方法以及如何使用委托实现异步操作。 1. **声明委托** 首先,我们需要定义一个委托类型,这将描述我们打算异步...

    通过委托和异步调用实现窗体间的通讯

    本文将深入探讨如何利用C#中的委托和异步调用来实现这种通讯。 首先,我们需要理解什么是委托。在C#中,委托类似于函数指针,它允许我们将方法作为参数传递,或者存储一个或多个方法以便稍后调用。委托是类型安全的...

    C# 异步编程 AsyncCallback委托

    C# 异步编程 AsyncCallback 委托 C# 异步编程是指在编程过程中,使用异步方法来调用其他方法或服务,而不是使用同步方法。异步方法的优点是可以提高程序的执行效率和响应速度,因为它可以在被调用方法完成任务的...

    委托的异步回调简单例子

    在这个"委托的异步回调简单例子"中,我们可以预期看到如何在Visual Studio 2010环境下利用委托实现异步回调的步骤和代码示例。异步回调通常与.NET Framework的`AsyncResult`类一起使用,它是`IAsyncResult`接口的一...

    VS2010轻松学习C#-从零到深入-天轰穿.NET4趣味编程视频教程_第43讲:线程通信与异步委托

    在本节"VS2010轻松学习C#-从零到深入-天轰穿.NET4趣味编程视频教程_第43讲:线程通信与异步委托"中,我们将探讨C#编程中的两个核心概念:线程通信和异步委托。线程通信是多线程编程中的关键组成部分,它允许不同线程...

    TCP(委托、线程、同步、异步学习程序源码)

    本文将深入探讨TCP网络编程中的关键概念,包括委托、线程、同步和异步,这些都是构建高效、可靠的网络应用的核心要素。 首先,TCP是一种面向连接的、可靠的传输协议,它在数据交换前会先建立连接,并通过三次握手...

    C#异步操作 异步查询数据库 异步处理一行一行加载数据

    在C#编程中,异步操作是现代应用开发的关键特性,尤其在处理大量数据或进行I/O密集型任务时,如查询数据库。本主题将深入探讨C#中的异步概念,如何异步查询数据库,以及如何异步处理一行一行加载的数据。 首先,...

Global site tag (gtag.js) - Google Analytics