C# 什么';s QueueUserWorkItem()和BeginInvoke()之间的区别,用于执行不需要返回类型的异步活动
下面是我的BeginInvoke()/EndInvoke()问题,Delegate.BeginInvoke()和使用QueueUserWorkItem()之间在性能/其他方面是否存在重大差异要异步调用委托?我能想到的关于C# 什么';s QueueUserWorkItem()和BeginInvoke()之间的区别,用于执行不需要返回类型的异步活动,c#,multithreading,delegates,C#,Multithreading,Delegates,下面是我的BeginInvoke()/EndInvoke()问题,Delegate.BeginInvoke()和使用QueueUserWorkItem()之间在性能/其他方面是否存在重大差异要异步调用委托?我能想到的关于QueueUserWorkItem的主要问题是,您必须使用WaitCallback委托类型,如果您已经有SomeRandomDelegate实例和一些参数,这看起来很棘手。好消息是,您可以通过关闭来修复此问题: ThreadPool.QueueUserWorkItem(
QueueUserWorkItem
的主要问题是,您必须使用WaitCallback
委托类型,如果您已经有SomeRandomDelegate
实例和一些参数,这看起来很棘手。好消息是,您可以通过关闭来修复此问题:
ThreadPool.QueueUserWorkItem(
delegate { someDelegate(arg1, arg2); }
);
此模式还确保在编译时获得适当的强类型(不同于将对象
状态参数传递给队列用户工作项
并在目标方法中强制转换)。直接调用方法时也可以使用此模式:
ThreadPool.QueueUserWorkItem(
delegate { SomeMethod(arg1, arg2); }
);
显然,如果没有等价的
EndInvoke
,也无法返回值,除非在方法末尾调用方法/引发事件/etc。。。另一方面,您需要注意。应该没有什么大的区别,我还认为为委托生成的BeginInvoke/EndInvoke使用线程池来执行。不应该有任何性能差异,因为Delegate.BeginInvoke和ThreadPool.QueueUserWorkItem都将在线程池线程上执行
最大的区别是,如果调用BeginInvoke,则必须在某个时候调用EndInvoke。相比之下,ThreadPool.QueueUserWorkItem是“激发并忘记”。这有好处也有缺点。好处是你可以忘记它。缺点是,除非您添加自己的同步/通知机制,否则无法知道任务何时完成。
说:
“一个令人惊讶的事实是,这是
还有为什么Delegate.BeginInvoke/
EndInvoke的速度比
等效技术,如
ThreadPool.QueueUserWorkItem(或
如果您
了解安全含义
并且想要真正高效
BeginInvoke/EndInvoke的代码路径
很快就变成了共同的信息
通用计算机的处理代码
远程处理途径。”
EndInvoke()有一个有用但很少提及的行为—它重新引用委托在原始线程上下文中生成的所有未处理异常,以便您可以将异常处理逻辑移到主代码中
此外,如果您的委托具有out/ref参数,则这些参数将添加到EndInvoke()签名中,允许您在方法完成执行时获取这些参数。如果调用ThreadPool.QueueUserWorkItem,则工作项中引发的异常将在后台线程上未处理(除非您显式捕获它们)。在.Net 2及更高版本中,这将终止您的AppDomain
如果调用delegate.BeginInvoke(),则调用EndInvoke()时,异常将排队重新引发。如果从未调用EndInvoke(),那么异常本质上是“泄漏”内存(异步操作未释放的任何其他状态也是如此)。遇到这种情况是我第一次对自己说,“哇,我喜欢闭包。”哇,这是一个绝妙的提示。它感觉像是一种装箱/拆箱语义,我想象在没有更高成本的情况下,在广泛的情况下。从技术上讲,它应该是“委托(对象o)”或类似的,以便代码能够编译,我相信,因为QueueUserWorkItem需要一个与WaitCallback匹配的委托签名,即。,包含object类型的单个参数的参数。@EnocNRoll-no;lambdas必须声明正确的参数;但是,anon方法可以选择忽略参数。代码是正确的。你绝对正确!这是一个非常有趣的细微差别。我终于有机会重新测试这个。我认为使用lambda包装对QueueuserWorkItem的调用无意中给了我错误的印象。感谢您的回复和更正!嗯,谢谢,这既有趣又吓人。我想我会回滚任何不需要返回值的BeginInvoke()/EndInvoke()代码!您可能还希望看到: