10

下面两段代码有什么区别?使用第二个会有什么问题吗?

场景一:

private void Log(Exception e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(Log), e);
}

private void Log(object obj)
{
    Exception e = (Exception)obj;
    Logger.Log(e);
}

方案 2

private void Log(Exception e)
{
    ThreadPool.QueueUserWorkItem(
        (obj) => 
            {
                Logger.Log(e);
            });
}

在场景 2 中,我没有将异常作为参数传递给 ThreadPool。异常对象的线程编组是如何发生的?会不会有什么问题?如果有的话,这样做有什么限制?最大的优势是您可以非常轻松地传入任意数量的参数。

4

2 回答 2

14

唯一的区别是,在场景二中,您正在关闭e变量,该变量有效地将堆栈变量e移动到移动到堆中的自定义类型,这样您就不会丢失它。

我认为这应该可以正常工作。

编辑:至于性能,这两种情况之间不应该有显着差异。在场景 1 中,您已经将异常传递state给在QueueUserWorkItem内部将该异常引用移动到堆上的方法。唯一的开销是,当您使用闭包时,编译器会为您创建一个类型并将任何捕获的变量存储为该类型的字段。

于 2009-05-08T16:51:49.613 回答
1

请注意,您可以使用匿名方法来代替 Lambda,它也可以在 C# 2.0 中工作:

ThreadPool.QueueUserWorkItem(delegate(Object e) 
    { 
        Logger.Log(e as Exception); 
    });
于 2009-05-08T18:03:49.690 回答