【转】delegate.BeginInvoke 注意事项

在工作中经常用到一些异步处理,这时会用到多线程。其实在很多时候都可以使用 delegate.BeginInvoke的方式来实现异步,避免了使用线程类。

 

但作为一个基础的知识点,您还是应该注意:

 

1、参数传递:
   private Func<int,string> DoSomting;
   private void Do()
   {
      DoSomting = new Func<int,string>(ShowMess);

      AsyncCallback callBack = new AsyncCallback(CallBack);
      IAsyncResult re = DoSomting.BeginInvoke( 10 /*代理所指方法的参数列表*/ , CallBack /*回掉方法*/ , null/*需要给CallBack方法的参数*/ );
      DoSomting.EndInvoke(re);
   }
   private string ShowMess(int value)
   {
      return "测试";
   }
   private void CallBack(IAsyncResult re)
   {
   }
2、返回值
   获取 EndInvoke 执行后的返回值。
   更改上面的代码,获取ShowMess的返回值

   IAsyncResult re = DoSomting.BeginInvoke( 10 , CallBack  , null);
   var mess = DoSomting.EndInvoke(re);//mess 为ShowMess方法的返回值

3、BeginInvoke 回掉方法的执行.

   private void CallBack(IAsyncResult re)
   {
            Func<int,string> doSomting = re.AsyncState as Func<int, string>;
            doSomting.EndInvoke(re);

            MessageBox.Show("完成!");
   }

   a、传递参数
      IAsyncResult re = DoSomting.BeginInvoke( 10 /*代理所指方法的参数列表*/ , CallBack /*回掉方法*/ , DoSomting/*需要给CallBack方法的参数*/ );
   b、使用re.AsyncState获取参数.

4、IAsyncResult 的 AsyncWaitHandle.WaitOne(int,bool);的执行。
   
   int : 表示等待的时间。

   bool: true 在等待int间隔后,如果还未结束,则继续等待。
         false在等待int间隔后,如果还未结束,则终止等待。

转载于:https://www.cnblogs.com/xlhblogs/archive/2012/12/26/2833367.html

<think>嗯,用户之前问了关于Action类和Invoke方法的问题,现在又问委托(delegate)怎么用以及委托到底是什么。看起来他们可能在学C#,特别是委托和事件处理这部分。需要先回顾一下之前的回答,确保内容连贯,但这次要更基础一些,因为用户现在问的是delegate的基础概念和使用方法。 首先,用户之前的问题已经涉及到了Action,而Action是预定义的委托类型。现在他们可能想了解更底层的委托机制,即如何自定义委托,而不仅仅是使用系统提供的Action或Func。因此,需要从委托的基本定义讲起,说明委托是什么,和类的关系,以及如何声明和使用。 用户可能对委托的概念还不太清楚,所以需要比喻或例子来帮助理解。比如,把委托比作函数指针,或者回调机制,这样更容易理解。另外,他们可能想知道为什么需要委托,以及在实际编程中委托的应用场景,比如事件处理、回调方法等。 接下来,用户的问题包括“delegate怎么用”,需要分步骤说明如何声明委托、实例化委托、多播委托等。要注意示例代码的简洁性,用简单的例子展示委托的定义和调用过程。同时,要对比系统内置的Action和Func,说明自定义委托和它们的区别,以及何时使用哪种更合适。 另外,用户可能对委托和事件的关系有疑问,虽然问题中没有提到事件,但可能需要简要提及,因为事件是基于委托的。但为了避免信息过载,可能先集中在委托本身,除非用户的问题扩展到事件。 还要注意用户可能遇到的常见错误,比如空引用异常,或者忘记取消订阅导致的内存泄漏。这些在之前的回答中也有提到,这里可以再次强调,以加强记忆。 最后,需要总结委托的核心要点,确保用户理解委托的作用、声明方法、使用场景和注意事项。使用列表或对比表格可以帮助整理信息,使其更清晰易懂。同时,提供实际的应用示例,如UI事件、异步回调等,让用户看到委托的实际价值。 总的来说,回答需要结构清晰,从定义到使用,再到实际应用和常见问题,逐步深入,避免使用过多专业术语,用简单易懂的语言和示例帮助用户建立对委托的全面理解。</think>以下是对C#委托(delegate)的完整解析,采用技术手册风格呈现: --- ### 一、委托本质解析 #### 1. 核心定义 - **类型本质**:委托是面向函数指针的类型安全封装类 - **核心能力**:实现方法引用的存储与传递 - **内存模型**:每个委托实例独立存储于堆内存中 #### 2. 技术定位 | 维度 | 描述 | |-------------|-------------------------------| | CLR类型 | 派生自`System.Delegate`的类 | | 编译产物 | 生成包含`Invoke`方法的完整类 | | 类型安全 | 强制校验方法签名匹配 | --- ### 二、委托声明规范 #### 1. 标准声明格式 ```csharp // 完整声明模板 [访问修饰符] delegate [返回值类型] 委托名([参数列表]); // 实际示例 public delegate void LogHandler(string message, int severity); ``` #### 2. 现代简化方案 ```csharp // 使用内置泛型委托替代自定义声明 Action<string, int> logAction; // 等效上述LogHandler ``` --- ### 三、委托操作全流程 #### 1. 基础使用步骤 ```csharp // 步骤1:声明委托类型 delegate void DataProcessor(int[] data); // 步骤2:定义匹配方法 void SortData(int[] arr) { Array.Sort(arr); } void PrintData(int[] arr) { Console.WriteLine(string.Join(",", arr)); } // 步骤3:实例化委托链 DataProcessor processor = SortData; processor += PrintData; // 多播委托 // 步骤4:触发执行 int[] numbers = {5,3,9}; processor(numbers); // 等效processor.Invoke(numbers) ``` #### 2. 参数传递机制 - **同步调用**:`Invoke()`直接在当前线程执行 - **异步调用**:`BeginInvoke()`启动独立线程 --- ### 四、委托与Lambda表达式 #### 1. 匿名方法绑定 ```csharp delegate int MathOp(int x, int y); MathOp add = delegate(int a, int b) { return a + b; }; // C# 2.0 MathOp multiply = (a, b) => a * b; // C# 3.0+ Lambda ``` #### 2. 闭包捕获示例 ```csharp int baseValue = 10; MathOp adder = x => x + baseValue; // 捕获外部变量 Console.WriteLine(adder(5)); // 输出15 ``` --- ### 五、关键应用场景 #### 1. 事件系统基础 ```csharp class TemperatureMonitor { // 声明基于委托的事件 public delegate void AlertHandler(float temp); public event AlertHandler OnOverheat; void CheckTemperature() { if(currentTemp > 100) { OnOverheat?.Invoke(currentTemp); // 触发警报 } } } ``` #### 2. 策略模式实现 ```csharp delegate bool FilterCondition(string item); void ProcessData(List<string> data, FilterCondition filter) { foreach(var item in data.Where(i => filter(i))) { // 处理符合条件的数据 } } // 使用示例 ProcessData(list, s => s.Length > 5); // Lambda条件 ``` --- ### 六、委托技术细节 #### 1. 内存结构剖析 ``` 委托实例内存布局: +-------------------+ | Method Pointer | -> 指向目标方法的地址 | Target Object | -> 实例方法的所属对象(静态方法为null) | Invocation List | -> 多播委托的方法链 +-------------------+ ``` #### 2. 性能优化要点 - 避免高频创建委托实例(可缓存复用) - 使用`MethodImplOptions.AggressiveInlining`优化小委托 - 对性能敏感场景优先使用静态方法 --- ### 七、委托与接口对比 | 维度 | 委托 | 接口 | |-----------------|-------------------------------|-------------------------------| | 绑定方法数 | 单方法/多播链 | 需实现多个方法 | | 版本兼容 | 新增方法不影响已有代码 | 新增方法破坏现有实现 | | 使用场景 | 事件回调、算法注入 | 定义对象契约 | | 运行时开销 | 调用成本较低 | 涉及虚方法表查询 | --- ### 八、调试与诊断 #### 1. 查看委托内容 ```csharp var delegates = myDelegate.GetInvocationList(); foreach(var d in delegates) { Console.WriteLine($"Method: {d.Method.Name}, Target: {d.Target}"); } ``` #### 2. 常见异常处理 - **NullReferenceException**:调用前检查null ```csharp if(myDelegate != null) { myDelegate(args); } ``` - **InvalidOperationException**:确保委托链未被修改 --- ### 九、现代C#演进 #### 1. 本地函数委托 ```csharp void ProcessData() { int counter = 0; // 本地函数作为委托 void Increment() { counter++; } var action = (Action)Increment; action(); } ``` #### 2. 函数指针(C# 9+) ```csharp unsafe { delegate* managed<int, int, int> funcPtr = &Add; int result = funcPtr(3, 5); } ``` --- ### 最佳实践原则 1. **命名规范**:委托类型以`Handler`或`Callback`结尾 2. **线程安全**:多线程环境使用`lock`保护委托链 3. **资源释放**:及时移除不需要的委托引用 4. **类型选择**:优先使用`Func<>`/`Action<>`简化声明 通过这个结构可以系统性地掌握C#委托的核心原理和实际应用技巧。建议通过Unity事件系统或ASP.NET Core中间件等具体场景加深理解。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值