Резьбовые и лямбда-выражения

В чем разница между двумя частями кода ниже? Будут ли какие-либо проблемы с использованием второго?

Сценарий 1:

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. Как происходит сортировка потоков объекта исключения? Будут ли проблемы? Каковы ограничения этого, если они есть? Большим преимуществом является то, что вы можете легко передать любое количество параметров.

Ответ 1

Единственное различие заключается в том, что во втором сценарии вы закрываете переменную e, которая эффективно перемещает переменную стека e в настраиваемый тип, который перемещается в кучу, поэтому вы не теряете его.

Я думаю, что это должно работать нормально.

Изменить: Что касается производительности, не должно быть существенной разницы между этими двумя сценариями. В сценарии 1 вы уже передаете исключение как state методу QueueUserWorkItem, который внутренне перемещает эту ссылку исключения в кучу. Единственные накладные расходы - это то, что когда вы используете закрытие, компилятор создает для вас тип и сохраняет любые захваченные переменные в виде полей этого типа.

Ответ 2

Просто заметим, что вместо Lambda вы можете сделать то же самое с анонимным методом, и он также будет работать в С# 2.0:

ThreadPool.QueueUserWorkItem(delegate(Object e) 
    { 
        Logger.Log(e as Exception); 
    });