将一个匿名委托传递给一个线程......为什么这个工作?

时间:2010-11-30 20:48:38

标签: c# .net multithreading stylecop anonymous-delegates

在我的程序中,我们分割了大量需要在四个线程中查看的数据。

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 个答案:

答案 0 :(得分:7)

您有两种选择:

  • 忽略StyleCop警告(推荐)
  • 将其更改为new ThreadStart(delegate { ... })

说明:

没有括号的匿名方法(delegate { ... })具有隐式参数列表。编译器将为其提供匹配其所使用的委托所需的任何参数。 (您的代码无法查看参数)
在编写不使用其参数的匿名事件处理程序时,这非常有用;它可以帮助您免于键入delegate(object sender, EventArgs e) { ... }

但是,在调用Thread构造函数时,有两种不同的重载需要两种代理。
编译器无法知道您尝试创建哪种委托类型,因为您没有指定参数列表。

答案 1 :(得分:5)

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 :(得分:2)

您可以使用lambda表达式而不是delegate关键字:

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