代码之家  ›  专栏  ›  技术社区  ›  endian

QueueUserWorkItem()和BeginInvoke()之间的区别是什么,它们执行异步活动时不需要返回类型

  •  15
  • endian  · 技术社区  · 16 年前

    6 回复  |  直到 16 年前
        1
  •  22
  •   Community CDub    7 年前

    我能想到的最重要的是 QueueUserWorkItem 就是你必须使用 WaitCallback 如果你已经有一个 SomeRandomDelegate 实例和一些参数。好消息是,您可以通过关闭来修复此问题:

    ThreadPool.QueueUserWorkItem(
        delegate { someDelegate(arg1, arg2); }
    );
    

    此模式还确保在编译时获得正确的强类型(与传递 object 状态arg到 QueueUserWorkItem 并在目标方法中投射)。直接调用方法时也可以使用此模式:

    ThreadPool.QueueUserWorkItem(
        delegate { SomeMethod(arg1, arg2); }
    );
    

    显然,没有 EndInvoke 同样,除非在方法末尾调用方法/引发事件/etc,否则也无法返回返回值。。。与此相关的一点是,你需要小心 exception handling .

        2
  •  18
  •   Pac0    5 年前

    http://blogs.msdn.com/cbrumme/archive/2003/07/14/51495.aspx

    说:

    还有为什么Delegate.BeginInvoke/ EndInvoke的速度比 等效技术,如 ThreadPool.QueueUserWorkItem(或 如果您 了解安全含义 并且想要真正高效)。这个 BeginInvoke/EndInvoke的代码路径 很快就变成了共同的信息 通用计算机的处理代码 远程处理途径。”

        3
  •  16
  •   IlyaP    15 年前

    EndInvoke()有一个有用但很少提及的行为—它重新引用委托在原始线程上下文中生成的所有未处理异常,以便您可以将异常处理逻辑移到主代码中。

    此外,如果您的委托具有out/ref参数,则它们将添加到EndInvoke()签名中,以便您在方法完成执行时获取它们。

        4
  •  4
  •   piers7    15 年前

    如果调用ThreadPool.QueueUserWorkItem,则工作项中引发的异常将在后台线程上未处理(除非您显式捕获它们)。在.Net 2及更高版本中,这将终止您的AppDomain。

    如果调用delegate.BeginInvoke(),则调用EndInvoke()时,异常将排队重新引发。如果从未调用EndInvoke(),则异常本质上是“泄漏”内存(与异步操作未释放的任何其他状态一样)。

        5
  •  -1
  •   Maghis    16 年前

    应该没有什么大的区别,我还认为为委托生成的BeginInvoke/EndInvoke使用线程池来执行。

        6
  •  -1
  •   Jim Mischel    16 年前

    应该没有任何性能差异,因为Delegate.BeginInvoke和ThreadPool.QueueUserWorkItem都将在线程池线程上执行。

    最大的区别是,如果调用BeginInvoke,则必须在某个时候调用EndInvoke。相比之下,ThreadPool.QueueUserWorkItem是“激发并忘记”。这有好处也有缺点。好处是你可以忘记它。缺点是,除非添加自己的同步/通知机制,否则无法知道任务何时完成。