跳转到主内容
极星编程网:以代码为星,赴技术山海!

C# 委托中 Invoke/BeginInvoke/EndInvoke和DynamicInvoke 方法的区别和联系

目录前言

一、 Invoke方法

1. 定义

2. 特点

3. 示例代码

二、 BeginInvoke 和 EndInvoke 方法

1. 定义

2. 特点

3. 示例代码

三、DynamicInvoke 方法

1. 定义

2. 特点

3. 示例代码

四、比较与总结

1. 概览

2. 具体区别与联系

3. 实际应用建议

4. 联系与协作

5. 注意事项

前言在C#中,委托(Delegate)提供了多种调用方式,包括Invoke、BeginInvoke、EndInvoke和DynamicInvoke。每种调用方式都有其特定的用途和适用场景。下面将详细介绍这些方法的区别与联系。

一、 Invoke方法

1. 定义

Invoke是同步调用委托的方法。它会阻塞当前线程,直到委托所引用的方法执行完毕并返回结果。

2. 特点

同步调用:当前线程会被阻塞,直到委托方法执行完成。

简单直接:适用于不需要异步处理的场景。

3. 示例代码

public class Program{public static void Main(){// 定义委托Action action = () => Console.WriteLine("Hello, World!");// 同步调用action.Invoke();}}public class Program{public delegate string SimpleDelegate(string message);public static string PrintMessage(string message){Console.WriteLine($"Message: {message}");return "Done";}public static void Main(){SimpleDelegate del = PrintMessage;string result = del.Invoke("Hello, World!"); // 同步调用Console.WriteLine(result);}}输出结果Message: Hello, World!

Done

二、 BeginInvoke 和 EndInvoke 方法

1. 定义

BeginInvoke和EndInvoke方法用于异步调用委托所引用的方法。

BeginInvoke方法启动异步操作并立即返回一个IAsyncResult对象,该对象可以用于跟踪异步操作的状态。而EndInvoke方法用于获取异步调用的结果或等待异步调用完成。

2. 特点

BeginInvoke异步调用:当前线程不会被阻塞,委托方法将在后台线程上执行。

回调机制:可以通过提供一个回调函数,在委托方法完成后自动调用该回调函数。

参数传递:除了委托方法的参数外,还需要传递一个AsyncCallback委托和一个用户定义的对象(通常是null)。

EndInvoke获取结果:通过传入BeginInvoke返回的IAsyncResult对象来获取异步调用的结果。

等待完成:如果异步调用尚未完成,EndInvoke将阻塞当前线程,直到异步调用完成。

3. 示例代码

using System;public class Program{public delegate string SimpleDelegate(string message);public static string PrintMessage(string message){Console.WriteLine($"Message: {message}");return "Done";}public static void Main(){SimpleDelegate del = PrintMessage;IAsyncResult asyncResult = del.BeginInvoke("Hello, World!", null, null); // 异步调用Console.WriteLine("Main method continues...");// 等待异步调用完成并获取结果string result = del.EndInvoke(asyncResult);Console.WriteLine(result);}}输出结果Main method continues...

Message: Hello, World!

Doneusing System;using System.Threading;public class Program{public static void Main(){// 定义委托Func func = () =>{Thread.Sleep(2000);Console.WriteLine("Asynchronous operation completed.");return 42;};// 异步调用IAsyncResult result = func.BeginInvoke(null, null);// 执行其他操作Console.WriteLine("Performing other tasks while waiting...");// 等待异步操作完成并获取结果int returnValue = func.EndInvoke(result);Console.WriteLine($"Return value: {returnValue}");}}

三、DynamicInvoke 方法

1. 定义

DynamicInvoke是一种动态调用委托的方法,允许以任意类型的参数调用委托,而不需要指定具体的参数类型。

与Invoke不同,DynamicInvoke可以在运行时动态地确定要调用的方法,并且可以处理参数和返回值的类型。

2. 特点

灵活性高:可以在运行时动态确定参数类型和数量。

性能较低:由于需要进行类型检查和转换,性能通常低于直接调用(如Invoke或BeginInvoke)。

3. 示例代码

using System;public class Program{public delegate string SimpleDelegate(string message);public static string PrintMessage(string message){Console.WriteLine($"Message: {message}");return "Done";}public static void Main(){SimpleDelegate del = PrintMessage;object[] args = new object[] { "Hello, DynamicInvoke!" };string result = (string)del.DynamicInvoke(args); // 动态调用Console.WriteLine(result);}}输出结果Message: Hello, DynamicInvoke!

Doneusing System;public class Program{public static void Main(){// 定义委托Func add = (a, b) => a + b;// 动态调用object result = add.DynamicInvoke(2, 3);Console.WriteLine($"Result: {result}"); //输出:Result: 5}}

四、比较与总结

1. 概览

方法调用方式是否阻塞当前线程参数类型要求性能主要应用场景Invoke同步是固定高简单同步调用BeginInvoke异步否固定中等异步调用EndInvoke同步是固定中等获取异步调用结果DynamicInvoke动态是动态低运行时动态调用

2. 具体区别与联系

InvokevsBeginInvokeInvoke是同步调用,会阻塞当前线程直到方法执行完成;

BeginInvoke是异步调用,不会阻塞当前线程。

Invoke适用于需要立即得到结果的场景;

BeginInvoke适用于需要提高响应速度、避免阻塞主线程的场景。

BeginInvokevsEndInvokeBeginInvoke用于启动异步调用,返回一个IAsyncResult对象;

EndInvoke用于获取异步调用的结果或等待异步调用完成。

在使用BeginInvoke后,必须调用EndInvoke来确保资源释放和获取结果。

DynamicInvokeDynamicInvoke提供了极大的灵活性,但代价是性能较低,因为它需要在运行时进行类型检查和转换。

适用于需要在运行时动态确定参数类型和数量的场景。

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# 委托中 Invoke/BeginInvoke/EndInvoke和DynamicInvoke 方法的文章就介绍到这了,更多相关C# 委托 Invoke/BeginInvoke/EndInvoke和DynamicInvoke内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

您可能感兴趣的文章:C#线程委托BeginInvoke与EndInvoke的用法C#用委托BeginInvoke做异步线程C#线程 BeginInvoke和EndInvoke使用方法

相关文章