C#LearningTutorial:TypesafeFire-and-Forget异步委托调用在C#Share异步地。理想情况下,我想做的是:varmyAction=(Action)(()=>Console.WriteLine("yadayada"));myAction.FireAndForget();//asyncinvocation不幸的是,当没有相应的EndInvoke()BeginInvoke()情况下调用BeginInvoke()的明显选择不起作用-它会导致缓慢的资源泄漏(因为asyn状态由运行时保存,永远不会发布...它期望最终调用EndInvoke()。我也无法让它在.NET线程池中工作,因为它可能需要很长时间才能完成(建议只在线程上运行相对短暂的代码pool)-这使得无法使用ThreadPool.QueueUserWorkItem()。最初,我只对带有Action的签名感兴趣,Action或Func匹配方法只需要这种行为。所以我整理了一组扩展方法(见下面的列表)让我这样做而不会遇到资源泄漏。每个版本的Action/Func都有重载。不幸的是,我现在想将此代码移植到.NET4,其中Action和Func的泛型参数数量急剧增加。在我编写T4脚本来生成这些之前,我也希望找到一种更简单、更优雅的方法来实现这一点。欢迎任何想法。publicstaticclassAsyncExt{publicstaticvoidFireAndForget(thisActionaction){action.BeginInvoke(OnActionCompleted,action);}publicstaticvoidFireAndForget(这个Action动作,T1arg1){action.BeginInvoke(arg1,OnActionCompleted,action);}publicstaticvoidFireAndForget(这个Actionaction,T1arg1,T2arg2){action.BeginInvoke(arg1,arg2,OnActionCompleted,action);}publicstaticvoidFireAndForget(thisFuncfunc,TResultarg1){func.BeginInvoke(OnFuncCompleted,func);}publicstaticvoidFireAndForget(thisFuncaction,T1arg1){action.BeginInvoke(arg1,OnFuncCompleted,action);}//为Action和Func重载FireAndForget()privatestaticvoidOnActionCompleted(IAsyncResultresult){varaction=(Action)result.AsyncState;action.EndInvoke(结果);}privatestaticvoidOnActionCompleted(IAsyncResultresult){varaction=(Action)result.AsyncState;action.EndInvoke(结果);}私有静态无效OnActionCompleted(IAsyncResult结果){varaction=(Action)result.AsyncState;action.EndInvoke(结果);}privatestaticvoidOnFuncCompleted(IAsyncResultresult){varfunc=(Func)result.AsyncState;func.EndInvoke(结果);}privatestaticvoidOnFuncCompleted(IAsyncResultresult){varfunc=(Func)result.AsyncState;func.EndInvoke(结果);}//OnActionCompleted和OnFuncCompleted的更多重载}您可以将EndInvoke作为AsyncCallback传递给BeginInvoke:Actionaction=//...action.BeginInvoke(buffer,0,buffer.Length,action.EndInvoke,null);这有帮助吗?我注意到没有人对此做出回应:我也无法在.NET线程池上运行代码,因为它可能需要很长时间才能完成(建议只在线程池上运行相对短暂的代码)——这使得它不可能使用ThreadPoolQueueUserWorkItem()。我不确定您是否意识到这一点,但异步委托实际上是这样做的——它们将工作排队到ThreadPool的工作线程上,就像您使用QueueUserWorkItem一样。异步委托行为唯一不同的时候是它们是特殊的框架委托,如Stream.BeginRead或Socket.BeginSend。这些使用I/O完成端口。除非您在ASP.NET环境中使用数百个这样的任务,否则我建议您只使用线程池。ThreadPool.QueueUserWorkItem(s=>action());或者,在.NET4中,您可以使用任务工厂:Task.Factory.StartNew(action);(注意上面也使用了线程池!)怎么样:publicstaticclassFireAndForgetMethods{publicstaticvoidFireAndForget(thisActionact,Targ1){vartsk=Task.Factory.StartNew(()=>act(arg1),TaskCreationOptions.LongRunning);}}像这样使用它:Actionfoo=(t)=>{Thread.Sleep(t);};foo.FireAndForget(100);要添加类型安全,只需扩展辅助方法即可。T4可能是这里最好的。编译器生成的BeginInvoke方法也在线程池上调用(参考)。所以我认为ThreadPool.QueueUserWorkItem会很好,除非你对它有点明确(我猜未来的CLR可能会选择在不同的线程池上运行BeginInvoke的ed方法)。那个聪明的小伙子双向飞碟在这里接近这个主题。有一半时间,有一种不同的方法来“即发即弃”。您可以编写自己的线程池实现。这听起来像是工作,但实际上并非如此。那么您就不必遵守“只运行相对短命的代码”的建议。给这个扩展方法一个机会(每个C#是action.BeginInvoke(action.EndInvoke,null)一个好主意吗?)以确保没有内存泄漏:publicstaticvoidFireAndForget(thisActionaction){action.BeginInvoke(action.EndInvoke,null);以上就是C#学习教程分享的全部内容:Typesafefire-and-forgetasynchronousdelegatecallinC#,如果对大家有用需要进一步了解C#学习教程,希望大家多多关注——T1param1=someValue;T2参数2=其他值;(()=>myFunc(param1,param2)).FireAndForget();本文收集自网络,不代表立场。如涉及侵权,请点击右侧联系管理员删除。如需转载请注明出处:
