C#异步委托的三种实现 BeginInvoke / EndInvoke / IsCompleted

  • 本文将介绍C#异步委托的三种实现方式,并给出相关示例代码及解析。

注意事项

    1. 用委托开启线程的前提是:创建项目时必须选择“.NET Framework",如果选择的是”.Net Core“,在调用BeginInvoke时,系统会报错”Operation is not supported on this platform.“。
    1. 异步调用的另一个前提是:委托的方法列表中只能包含一个方法。

等待至完成

  • 通过BeginInvoke和EndInvoke实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FrameworkDemo
{
    public delegate long MyDel(int a, int b);
    class Program
    {
        static long sum(int a, int b) {
            Thread.Sleep(10 * 1000);
            return a + b;
        }
        static void Main(string[] args)
        {
            // 异步委托操作描述
            IAsyncResult res = null;

            long result = 0;
            AsyncCallback callback = ar =>
            {
                // 输出结果:“计算结果为:11”
                Console.WriteLine($"{ar.AsyncState}{result}");
            };
            MyDel del = new MyDel(sum);
            // BeginInvoke开启异步调用
            // res的打印结果为System.Runtime.Remoting.Messaging.AsyncResult
            res = del.BeginInvoke(3, 8, callback, "计算结果为");  
            // 等待线程结束,并获取返回值
            result = del.EndInvoke(res);
            Console.ReadLine();
        }
    }
}
  • BeginInvoke函数的最后两个参数分别是一个回调函数,以及传入这个回调函数的参数。当委托线程运行结束后,会自动运行这个回调函数。之前的参数个数及类型取决于定义委托时参数的类型和个数。
  • IAsyncResult类型表示对异步委托操作的描述,一调用异步委托,就立刻会在主函数中得到这个返回值,打印结果为“System.Runtime.Remoting.Messaging.AsyncResult”。
  • EndInvoke会把主线程卡主,知道异步委托方法结束,此时将之前拿到的异步委托操作描述作为参数传入,即可获得异步委托函数的真正返回值。

轮询模式

  • 通过IsCompleted实现。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace FrameworkDemo
{
    public delegate long MyDel(int a, int b);
    class Program
    {
        static long sum(int a, int b) {
            Thread.Sleep(10 * 1000);
            return a + b;
        }
        static void Main(string[] args)
        {
            // 异步委托操作描述
            IAsyncResult res = null;

            long result = 0;
            AsyncCallback callback = ar =>
            {
                // 输出结果:“计算结果为:11”
                Console.WriteLine($"{ar.AsyncState}{result}");
            };
            MyDel del = new MyDel(sum);
            // BeginInvoke开启异步调用
            // res的打印结果为System.Runtime.Remoting.Messaging.AsyncResult
            res = del.BeginInvoke(3, 8, callback, "计算结果为");
            while (!res.IsCompleted) {
                /*
                 一系列想要的操作
                 */
            }
            // 等待线程结束,并获取返回值
            result = del.EndInvoke(res);
            Console.ReadLine();
        }
    }
}
  • 之前我们调用BeginInvoke后,直接调用EndInvoke,这使得主线程一直卡主,直到委托线程返回,通过IsComplated进行轮询线程状态,我们可以在循环中利用等待时间,执行一些别的想要的工作。

回调

  • 关于回调函数,比较标准的写法如下:
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 FrameworkDemo
{
    public delegate long MyDel(int a, int b);
    class Program
    {
        static long sum(int a, int b) {
            Thread.Sleep(10 * 1000);
            return a + b;
        }
        // 异步委托执行完成后需要调用的回调函数
        static void testCallback(IAsyncResult ar) {
            System.Runtime.Remoting.Messaging.AsyncResult varResult =
             (System.Runtime.Remoting.Messaging.AsyncResult)ar;
            MyDel test = (MyDel)varResult.AsyncDelegate;
            long result = test.EndInvoke(ar);
            Console.WriteLine($"{ar.AsyncState}: {result}");
        }
        static void Main(string[] args)
        {           
            MyDel del = new MyDel(sum);
            AsyncCallback asyncTest = new AsyncCallback(testCallback);
            del.BeginInvoke(3, 8, asyncTest, "计算结果为");
            Console.ReadLine();
        }
    }
}
  • 当异步委托运行结束后,系统会自动调用回调函数,并将异步委托描述信息IAsyncResult作为参数传入回到函数中,因此我们需要做的就是解析异步委托描述信息。

你可能感兴趣的:(C#,C#,.NET,异步,多线程,委托)