当前位置: 首页 > 编程语言 > C#

C#事件:如何并行处理事件分享

时间:2023-04-11 11:04:51 C#

C#事件:如何并行处理事件我有一个事件,我想并行处理。我的想法是将每个回调添加到ThreadPool,有效地为每个注册的事件提供一个方法,由ThreadPool处理。我的试用代码如下所示:Delegate[]delegates=myEvent.GetInvocationList();IAsyncResult[]results=newIAsyncResult[delegates.Count()];for(inti=0;i2)?il.DeclareLocal(typeof(object[])):null;boolskipLoad=false;il.BeginExceptionBlock();il.Emit(OpCodes.Ldarg_1);//我们要调用的委托if(args!=null){Debug.Assert(args.LocalIndex==0);il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Ldfld,parallelInvokeContext_arguments);il.Emit(OpCodes.Dup);il.Emit(OpCodes.Stloc_0);跳过负载=真;}foreach(ParameterInfoparameterinparameters){if(parameter.ParameterType.IsByRef){thrownewInvalidOperationException(“TDelegate委托必须注意有out或ref参数”);}parameterTypes[parameter.Position]=parameter.ParameterType;如果(args==null){il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Ldfld,parallelInvokeContext_arguments);}elseif(skipLoad){skipLoad=false;}else{il.Emit(OpCodes.Ldloc_0);}il.Emit(OpCodes.Ldc_I4,parameter.Position);il.Emit(OpCodes.Ldelem_Ref);if(parameter.ParameterType.IsValueType){il.Emit(OpCodes.Unbox_Any,parameter.ParameterType);}}il.Emit(OpCodes.Callvirt,delegate_invoke);il.BeginFinallyBlock();il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Call,monitor_enter);il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Dup);il.Emit(OpCodes.Ldfld,parallelInvokeContext_activeCalls);il.Emit(OpCodes.Ldc_I4_1);il.Emit(OpCodes.Sub);il.Emit(OpCodes.Dup);标签noPulse=il.DefineLabel();il.Emit(OpCodes.Brtrue,noPulse);il.Emit(OpCodes.Stfld,parallelInvokeContext_activeCalls);il.Emit(OpCodes.Ldarg_0);il.Emit(OpCodes.Call,monitor_pulse);标签退出=il.DefineLabel();il.Emit(OpCodes.Br,exit);il.MarkLabel(无脉冲);il.Emit(OpCodes.Stfld,parallelInvokeContext_activeCalls);il.MarkLabel(退出);il.Emit(操作码s.Ldarg_0);il.Emit(OpCodes.Call,monitor_exit);il.EndExceptionBlock();il.Emit(OpCodes.Ret);}[Conditional("DEBUG")]privatestaticvoidVerifyArgumentsDebug(object[]args){for(inti=0;i0){if(args==null){thrownewArgumentNullException("args");}if(args.Length!=parameterTypes.Length){thrownewArgumentException("参数个数不匹配");}VerifyArgumentsDebug(args);参数=参数;}elseif((args!=null)&&(args.Length>0)){thrownewArgumentException("Thisdelegatedoesnotexpectanyparameters");}invokeCallback=(WaitCallback)invoker.CreateDelegate(typeof(WaitCallback),this);}publicvoidQueueInvoke(Delegate@delegate){Debug.Assert(@delegateisTDelegate);主动呼叫++;ThreadPool.QueueUserWorkItem(invokeCallback,@delegate);}}privatestaticreadonlyMethodInfomonitor_enter;privatestaticreadonlyMethodInfomonitor_exit;privatestaticreadonlyMethodInfomonitor_pulse;静压arallelInvoke(){monitor_enter=typeof(Monitor).GetMethod("Enter",BindingFlags.Static|BindingFlags.Public,null,new[]{typeof(object)},null);monitor_pulse=typeof(Monitor).GetMethod("Pulse",BindingFlags.Static|BindingFlags.Public,null,new[]{typeof(object)},null);monitor_exit=typeof(Monitor).GetMethod("Exit",BindingFlags.Static|BindingFlags.Public,null,new[]{typeof(object)},null);}publicstaticvoidInvoke(TDelegate@delegate)whereTDelegate:class{Invoke(@delegate,null);}publicstaticvoidInvoke(TDelegate@delegate,paramsobject[]args)whereTDelegate:class{if(@delegate==null){thrownewArgumentNullException("delegate");}ParallelInvokeContextcontext=newParallelInvokeContext(args);锁定(上下文){foreach(在((委托)(对象)@delegate)中委托调用委托)。GetInvocationList()){context.QueueInvoke(invocationDelegate);}Monitor.Wait(上下文);}}}使用方法:ParallelInvoke.Invoke(yourDelegate,参数);注意:如果委托的类型已知,可以直接调用它的BeginInvoke并将IAsyncResults存储在一个数组中等待并结束调用注意你应该调用EndInvoke以避免潜在的资源泄漏。该代码依赖于EndInvoke等待调用完成这一事实,因此不需要WaitAll(注意,WaitAll有几个问题,因此我避免使用它)。下面是代码示例和不同方法的简单基准:publicstaticclassMainClass{privatedelegatevoidTestDelegate(stringx);privatestaticvoidA(stringx){}privatestaticvoidInvoke(TestDelegatetest,strings){Delegate[]delegates=test.GetInvocationList();IAsyncResult[]results=newIAsyncResult[delegates.Length];for(inti=0;i在我的旧笔记本电脑上,使用BeginInvoke/EndInvoke花费了95553ms,而使用ParallelInvoke方法(MS.NET3.5)花费了9038ms。因此,与ParallelInvoke解决方案相比,此方法无法很好地扩展。你似乎在您的代码片段中执行两个异步启动。首先,在委托上调用BeginInvoke-这会将工作项排队,以便线程池将执行委托。然后在该委托中,使用QueueUserWorkItem将另一个工作项排队,以便线程池将执行真正的委托。这意味着当您从外部委托(以及等待句柄)返回IAsyncResult时,它将在第二个工作项排队时发出完成信号,而不是在它完成执行时发出信号。您这样做是为了提高性能吗?Onlyifitallowsyouhavemultiplehardware它只有在并行工作时才有效,并且它会花费你进程切换的开销。以上就是C#学习教程:C#Events:HowtoProcessEventsinParallel分享的全部内容,如果对大家有用,需要了解更多C#学习教程,希望大家多多关注---这篇文章来自网络收集,不代表立场,如涉及侵权,请点击右边联系管理员删除。如需转载请注明出处:

最新推荐
猜你喜欢