ThreadPool.QueueUserWorkItem с лямбда-выражением и анонимным методом

StackOverflow https://stackoverflow.com/questions/738139

Вопрос

Передача двух параметров новому потоку в threadpool иногда может быть сложной, но, похоже, с помощью лямбда-выражений и анонимных методов я могу это сделать:

public class TestClass
{
    public void DoWork(string s1, string s2)
    {
        Console.WriteLine(s1);
        Console.WriteLine(s2);
    }
}

try
{
    TestClass test = new TestClass();
    string s1 = "Hello";
    string s2 = "World";
    ThreadPool.QueueUserWorkItem(
        o => test.DoWork(s1, s2)
        );
}
catch (Exception ex)
{
    //exception logic
}

Я, конечно, упростил этот пример, но эти моменты являются ключевыми:

  • Передаваемые строковые объекты являются неизменяемыми и, следовательно, потокобезопасными
  • Переменные s1 и s2 объявлены в пределах области действия блока try, который я выхожу сразу после постановки работы в очередь пула потоков, поэтому переменные s1 и s2 после этого никогда не изменяются.

В этом есть что-то неправильное?

Альтернативой является создание нового класса, который реализует неизменяемый тип с 3 членами:тест, s1 и s2.На данный момент это просто кажется дополнительной работой, не приносящей никакой пользы.

Это было полезно?

Решение

В этом нет ничего плохого.Компилятор, по сути, автоматически выполняет то, что вы описали как свою альтернативу.Он создает класс для хранения захваченных переменных (test, s1 и s2) и передает экземпляр делегата лямбде, который превращается в метод анонимного класса.Другими словами, если бы вы продолжили свою альтернативу, то в итоге получили бы что-то очень похожее на то, что компилятор только что сгенерировал для вас.

Другие советы

Для этого конкретного примера, нет, здесь нет ничего плохого.Состояние, которое вы передали в другой поток, полностью содержится, и ни один из задействованных типов не имеет проблем с привязкой к потоку.

Это хороший способ сделать это.Я не вижу никаких недостатков в использовании лямбд.Это просто и понятно.

То, на что вы смотрите, называется завершением.Как государства чакдж, компилятор генерирует класс во время компиляции, который соответствует членам, к которым осуществляется доступ за пределами замыкания.

Единственное, о чем вам нужно беспокоиться, это о том, есть ли у вас параметры ref или out .Хотя строки неизменяемы, ссылки на них (или любую переменную) ТАКОВЫМИ НЕ являются.

Одна из потенциальных проблем с шаблоном заключается в том, что он очень заманчиво расширить его до чего-то более общего, но менее безопасного, подобного этому (scratch code - не ожидайте, что это сработает):

public static void QueueTwoParameterWorkItem<T1, T2>(T1 value1, T2 value2, workDelegate<T1,T2> work)
{
    try
    {
        T1 param1 = value1;
        T2 param2 = value2;
        ThreadPool.QueueUserWorkItem(
            (o) =>
            {
                work(param1, param2);
            });
    }
    catch (Exception ex)
    {
        //exception logic
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top