Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/322.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 什么';s QueueUserWorkItem()和BeginInvoke()之间的区别,用于执行不需要返回类型的异步活动_C#_Multithreading_Delegates - Fatal编程技术网

C# 什么';s QueueUserWorkItem()和BeginInvoke()之间的区别,用于执行不需要返回类型的异步活动

C# 什么';s QueueUserWorkItem()和BeginInvoke()之间的区别,用于执行不需要返回类型的异步活动,c#,multithreading,delegates,C#,Multithreading,Delegates,下面是我的BeginInvoke()/EndInvoke()问题,Delegate.BeginInvoke()和使用QueueUserWorkItem()之间在性能/其他方面是否存在重大差异要异步调用委托?我能想到的关于QueueUserWorkItem的主要问题是,您必须使用WaitCallback委托类型,如果您已经有SomeRandomDelegate实例和一些参数,这看起来很棘手。好消息是,您可以通过关闭来修复此问题: ThreadPool.QueueUserWorkItem(

下面是我的BeginInvoke()/EndInvoke()问题,Delegate.BeginInvoke()和使用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()代码!您可能还希望看到: