异步委托的使用

一.同步委托

委托类型可以分为同步委托和异步委托,同步委托通过Invoke来调用,如果要调用一项比较繁琐的工作时,同步委托则会阻塞,让程序停滞等待很长时间,直到委托中的工作完成后才能继续执行下去,这样的话会造成很不好的用户体检。

下例所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DelegateInvoke
{
    class Program
    {
        private delegate float DelegaetAdd(float a, float b);
        static void Main(string[] args)
        {
            DelegaetAdd myDelegate = new DelegaetAdd(Add);
            float subNum = myDelegate.Invoke(5, 6);
            Console.WriteLine("主线程继续执行。。。。。");
            Console.WriteLine("值为{0}", subNum);
            Console.ReadKey();
        }

        private static float Add(float a, float b)
        {
            Console.WriteLine("正在执行。。。。。。");
            Thread.Sleep(2000);

            return (a + b);
        }
    }
}

打印结果:

二.异步委托

由于同步委托为造成程序卡顿,造成不好的用户体检,那么此时使用异步委托便是再好不过了;异步委托是通过BeginInvoke和Endinvoke调用实现的。

下例所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DelegateInvoke
{
    class Program
    {
        private delegate float DelegaetAdd(float a, float b);
        static void Main(string[] args)
        {
            DelegaetAdd myDelegate = new DelegaetAdd(Add);
            IAsyncResult result = myDelegate.BeginInvoke(5, 6, null, null);
            Console.WriteLine("主线程继续执行。。。。。。");
            float subNum = myDelegate.EndInvoke(result);
            Console.WriteLine("值为{0}", subNum);
            Console.WriteLine("执行完毕。。。。。");
            Console.ReadKey();
        }

        private static float Add(float a, float b)
        {
            Console.WriteLine("正在执行。。。。。。");
            Thread.Sleep(2000);

            return (a + b);
        }
    }
}

打印结果:


 从打印结果中可以看出,主线程并没有去等待,而是直接就运行下去了,但是我们可以发现,当主线程运行到了EndInvoke,如果此时调用还没有结束的话,那么此时为了等待调用结果,线程依然会阻塞等待调用完成的。

三.异步回调

可以看出以上两种方法都不能解决调用时阻塞的问题,那么这时候,就该主角上场了,那就是异步回调了;用回调函数,当调用结束时会自动调用回调函数,能够很好地解决为了等待调用结果而导致主线程阻塞的问题。

下例所示:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Runtime.Remoting.Messaging;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace DelegateInvoke
{
    class Program
    {
        private delegate float DelegaetAdd(float a, float b);
        static void Main(string[] args)
        {
            DelegaetAdd myDelegate = new DelegaetAdd(Add);
            AsyncCallback callBack = new AsyncCallback(CallBack);
            IAsyncResult result = myDelegate.BeginInvoke(5, 6, callBack, "Completed");
            Console.WriteLine("主线程继续执行。。。。。。");
            Console.ReadKey();
        }

        //异步回调函数
        private static void CallBack(IAsyncResult result)
        {
            DelegaetAdd myDelegate = (DelegaetAdd)((AsyncResult)result).AsyncDelegate;
            if(result.IsCompleted)
            {
                Console.WriteLine("正在执行。。。。。");
                Thread.Sleep(2000);
                Console.WriteLine("值为{0}", myDelegate.EndInvoke(result));
                Console.WriteLine(result.AsyncState);
            }     
        }

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

打印结果:

BeginInvoke() 方法用于异步委托的执行开始,EndInvoke() 方法用于结束异步委托,并获取异步委托执行完成后的返回值。IAsyncResult.IsCompleted 用于监视异步委托的执行状态(true / false),一定要等到异步委托执行完成之后,这个属性才会返回 true。BeginInvoke() 是可以接受多个参数的,它的参数个数和参数类型取决于定义委托时的参数个数和类型,但是无论它有多少个参数,最后两个参数都是不变的;第一个便是委托类型AsyncCallBack(IAsyncResult result),第二个便是用户自定义的数据类型,IAsyncResult.AsyncState就是它的值。

猜你喜欢

转载自www.cnblogs.com/QingYiShouJiuRen/p/11224797.html