Передача анонимного делегата в поток ... почему это работает? - PullRequest
6 голосов
/ 30 ноября 2010

В моей программе мы разделили большой объем данных, которые необходимо просмотреть по четырем потокам.

Thread one = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });
Thread two = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[1], param2, param3, param4, param5); });
Thread three = new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[2], param2, param3, param4, param5); });
Thread four= new Thread(delegate() { NewMethod(recordsSplitIntoQuarters[3], param2, param3, param4, param5); });

Наши стандарты кодирования требуют, чтобы мы были как бы совместимы с StyleCop, а StyleCop требует следующего:

SA1410: удалите скобки из анонимного метода, посколькусписок параметров делегата пуст.

Это приводит к ошибке компилятора:

Вызов неоднозначен между следующими методами или свойствами: 'System.Threading.Thread.Thread (System.Threading.ParameterizedThreadStart) 'и' System.Threading.Thread.Thread (System.Threading.ThreadStart) '

Я просмотрел объекты ThreadStart и ParameterizedThreadStart и могу тольконе могу понять, как получить то, что мне нужно, с любым из этих объектов.

Мой вопрос: как работают анонимные делегаты?К чему они сводятся?В конце концов мне придется заставить это работать без анонимных делегатов, но я не знаю, с чего начать.

Спасибо за помощь,

Искатель

Ответы [ 3 ]

7 голосов
/ 30 ноября 2010

У вас есть два варианта:

  • Игнорировать предупреждение StyleCop (рекомендуется)
  • Измените его на new ThreadStart(delegate { ... })

Пояснение:

Анонимный метод без скобок (delegate { ... }) имеет список неявных параметров. Компилятор предоставит ему любые параметры, необходимые для соответствия делегату, в котором он используется. (Ваш код не видит параметры)
Это очень полезно при написании анонимных обработчиков событий, которые не используют свои параметры; это спасает вас от набора delegate(object sender, EventArgs e) { ... }.

Однако при вызове конструктора Thread есть две различные перегрузки, которые принимают два вида делегатов.
Компилятор не может узнать, какой тип делегата вы пытаетесь создать, поскольку вы не указали список параметров.

5 голосов
/ 30 ноября 2010

StyleCop задерживается.

StyleCop подразумевает, что оба синтаксиса имеют одинаковое значение. Это совершенно неверно. Пропуск скобок от делегата не означает «это не требует аргументов».Это означает «введите любые аргументы для меня, потому что я все равно не буду их использовать».

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

Если вы хотите сделать StyleCop счастливым и компилируйте ваш код, это один из вариантов:

Thread one = new Thread(new ThreadStart(delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); }));

Это другой вариант:

Thread one = new Thread((ThreadStart) delegate { NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5); });

Но я бы предложил LART авторам StyleCop ввести это смешное правило.

2 голосов
/ 30 ноября 2010

Вы можете использовать лямбда-выражение вместо ключевого слова delegate:

Thread one = new Thread(() => NewMethod(recordsSplitIntoQuarters[0], param2, param3, param4, param5));
...