C# 委托中 Invoke/BeginInvoke/EndInvoke和DynamicInvoke 方法

[复制链接]
发表于 2025-10-16 22:32:00 | 显示全部楼层 |阅读模式

马上注册,结交更多好友,享用更多功能,让你轻松玩转社区。

您需要 登录 才可以下载或查看,没有账号?立即注册

×
总目次


前言

在C#中,委托(Delegate)提供了多种调用方式,包罗 Invoke、BeginInvoke、EndInvoke 和 DynamicInvoke。每种调用方式都有其特定的用途和实用场景。下面将详细先容这些方法的区别与接洽。

一、 Invoke方法

1. 界说

Invoke 是同步调用委托的方法。它会壅闭当火线程,直到委托所引用的方法实验完毕并返回效果。
2. 特点



  • 同步调用:当火线程会被壅闭,直到委托方法实验完成。
  • 简朴直接:实用于不须要异步处置处罚的场景。
3. 示例代码

  1. public class Program
  2. {
  3.     public static void Main()
  4.     {
  5.         // 定义委托
  6.         Action action = () => Console.WriteLine("Hello, World!");
  7.         // 同步调用
  8.         action.Invoke();
  9.     }
  10. }
复制代码
  1. public class Program
  2. {
  3.     public delegate string SimpleDelegate(string message);
  4.     public static string PrintMessage(string message)
  5.     {
  6.         Console.WriteLine($"Message: {message}");
  7.         return "Done";
  8.     }
  9.     public static void Main()
  10.     {
  11.         SimpleDelegate del = PrintMessage;
  12.         string result = del.Invoke("Hello, World!"); // 同步调用
  13.         Console.WriteLine(result);
  14.     }
  15. }
复制代码
输出效果
  1. Message: Hello, World!
  2. Done
复制代码
二、 BeginInvoke 和 EndInvoke 方法

1. 界说

BeginInvoke 和 EndInvoke 方法用于异步调用委托所引用的方法。BeginInvoke 方法启动异步使用并立刻返回一个 IAsyncResult 对象,该对象可以用于跟踪异步使用的状态。而 EndInvoke 方法用于获取异步调用的效果或等待异步调用完成。
2. 特点



  • BeginInvoke

    • 异步调用:当火线程不会被壅闭,委托方法将在背景线程上实验。
    • 回调机制:可以通过提供一个回调函数,在委托方法完成后自动调用该回调函数。
    • 参数转达:除了委托方法的参数外,还须要转达一个 AsyncCallback 委托和一个用户界说的对象(通常是 null)。

  • EndInvoke

    • 获取效果:通过传入 BeginInvoke 返回的 IAsyncResult 对象来获取异步调用的效果。
    • 等待完成:如果异步调用尚未完成,EndInvoke 将壅闭当火线程,直到异步调用完成。

3. 示例代码

  1. using System;
  2. public class Program
  3. {
  4.     public delegate string SimpleDelegate(string message);
  5.     public static string PrintMessage(string message)
  6.     {
  7.         Console.WriteLine($"Message: {message}");
  8.         return "Done";
  9.     }
  10.     public static void Main()
  11.     {
  12.         SimpleDelegate del = PrintMessage;
  13.         IAsyncResult asyncResult = del.BeginInvoke("Hello, World!", null, null); // 异步调用
  14.         Console.WriteLine("Main method continues...");
  15.         // 等待异步调用完成并获取结果
  16.         string result = del.EndInvoke(asyncResult);
  17.         Console.WriteLine(result);
  18.     }
  19. }
复制代码
输出效果
  1. Main method continues...Message: Hello, World!
  2. Done
复制代码
  1. using System;
  2. using System.Threading;
  3. public class Program
  4. {
  5.     public static void Main()
  6.     {
  7.         // 定义委托
  8.         Func<int> func = () =>
  9.         {
  10.             Thread.Sleep(2000);
  11.             Console.WriteLine("Asynchronous operation completed.");
  12.             return 42;
  13.         };
  14.         // 异步调用
  15.         IAsyncResult result = func.BeginInvoke(null, null);
  16.         // 执行其他操作
  17.         Console.WriteLine("Performing other tasks while waiting...");
  18.         // 等待异步操作完成并获取结果
  19.         int returnValue = func.EndInvoke(result);
  20.         Console.WriteLine($"Return value: {returnValue}");
  21.     }
  22. }
复制代码
三、DynamicInvoke 方法

1. 界说

DynamicInvoke 是一种动态调用委托的方法,允许以恣意范例的参数调用委托,而不须要指定详细的参数范例。
与 Invoke 差别,DynamicInvoke 可以在运行时动态地确定要调用的方法,而且可以处置处罚参数和返回值的范例。
2. 特点



  • 机动性高:可以在运行时动态确定参数范例和数量。
  • 性能较低:由于须要举行范例查抄和转换,性能通常低于直接调用(如 Invoke 或 BeginInvoke)。
3. 示例代码

  1. using System;
  2. public class Program
  3. {
  4.     public delegate string SimpleDelegate(string message);
  5.     public static string PrintMessage(string message)
  6.     {
  7.         Console.WriteLine($"Message: {message}");
  8.         return "Done";
  9.     }
  10.     public static void Main()
  11.     {
  12.         SimpleDelegate del = PrintMessage;
  13.         object[] args = new object[] { "Hello, DynamicInvoke!" };
  14.         string result = (string)del.DynamicInvoke(args); // 动态调用
  15.         Console.WriteLine(result);
  16.     }
  17. }
复制代码
输出效果
  1. Message: Hello, DynamicInvoke!
  2. Done
复制代码
  1. using System;
  2. public class Program
  3. {
  4.     public static void Main()
  5.     {
  6.         // 定义委托
  7.         Func<int, int, int> add = (a, b) => a + b;
  8.         // 动态调用
  9.         object result = add.DynamicInvoke(2, 3);
  10.         Console.WriteLine($"Result: {result}");        //输出:Result: 5
  11.     }
  12. }
复制代码
四、比力与总结

1. 概览

方法调用方式是否壅闭当火线程参数范例要求性能重要应用场景Invoke同步是固定高简朴同步调用BeginInvoke异步否固定中等异步调用EndInvoke同步是固定中等获取异步调用效果DynamicInvoke动态是动态低运行时动态调用2. 详细区别与接洽


  • Invoke vs BeginInvoke

    • Invoke 是同步调用,会壅闭当火线程直到方法实验完成;BeginInvoke 是异步调用,不会壅闭当火线程。
    • Invoke 实用于须要立刻得到效果的场景;BeginInvoke 实用于须要进步相应速率、克制壅闭主线程的场景。

  • BeginInvoke vs EndInvoke

    • BeginInvoke 用于启动异步调用,返回一个 IAsyncResult 对象;EndInvoke 用于获取异步调用的效果或等待异步调用完成。
    • 在使用 BeginInvoke 后,必须调用 EndInvoke 来确保资源开释和获取效果。

  • DynamicInvoke

    • DynamicInvoke 提供了极大的机动性,但代价是性能较低,由于它须要在运行时举行范例查抄和转换。
    • 实用于须要在运行时动态确定参数范例和数量标场景。

3. 实际应用发起



  • 同步调用:如果你须要立刻得到效果而且不关心壅闭当火线程,使用 Invoke。
  • 异步调用:如果你渴望在不壅闭当火线程的环境下实验某个使用,使用 BeginInvoke 和 EndInvoke。
  • 动态调用:如果你须要在运行时动态确定参数范例和数量,使用 DynamicInvoke,但要注意其性能开销。
  • 及时数据展示:用 Control.BeginInvoke 异步更新 UI。
  • 批量盘算使命:通过 BeginInvoke 分发使命到线程池。
  • 插件体系:联合 DynamicInvoke 实现动态方法调用。
通过公道选择调用方式,可以在包管线程安全的同时提拔步调性能与相应速率。
4. 接洽与协作



  • 异步调用链:
    BeginInvoke 启动异步使命 → 通过 IAsyncResult 监控监控状态 → EndInvoke 获取效果,形成完备的异步流程。
  • 线程安全:
    UI 控件使用中,Control.Invoke 和 Control.BeginInvoke 逼迫在 UI 线程实验委托,克制跨线程访问非常。
  • 替换方案:
    当代 C# 保举使用 Task 和 async/await 替换 BeginInvoke/EndInvoke,因其代码可读性更高且资源管理更安全。
5. 注意事项


  • 性能开销:
    BeginInvoke 依靠线程池,频仍调用大概导致资源竞争;DynamicInvoke 的反射机制服从较低,慎用于高频场景。
  • 非常处置处罚:

    • Invoke 和 DynamicInvoke 的非常直接传播,需用 try-catch 包裹;
    • BeginInvoke 的非常需在 EndInvoke 中捕捉。

  • 代码优化:
    发布模式下,编译器大概内联方法,可通过 [MethodImpl(MethodImplOptions.NoInlining)] 保存堆栈信息。

结语

回到目次页:C#/.NET 知识汇总
渴望以上内容可以资助到各人,如文中有不对之处,还请品评指正。
回复

使用道具 举报

登录后关闭弹窗

登录参与点评抽奖  加入IT实名职场社区
去登录
快速回复 返回顶部 返回列表