如何通过lambda表达式“将任意数量的参数传递给线程”?

时间:2013-02-22 12:44:45

标签: c# multithreading delegates lambda closures

我跟随约瑟夫·阿尔巴哈里(Joseph Albahari)的“第1部分:开始使用”“C#中的线程”Passing Data to a Thread

即通道:

======报价开头

使用这种方法,您可以传入(到哪里?)任意数量的方法。您甚至可以将整个实现包装在多语句lambda中:< / em>的

new Thread (() =>  
{  
  Console.WriteLine ("I'm running on another thread!");  
  Console.WriteLine ("This is so easy!");  
}).Start();*  

您可以使用匿名方法在C#2.0中轻松完成同样的事情:

  new Thread (delegate()  
  {  
  ...
  }).Start();

============报价结束

也就是说,我已经尝试过“轻松”了:

new Thread
(delegate
  {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
   }
).Start();

但它会产生错误:

  

以下方法或属性之间的调用不明确:   'System.Threading.Thread.Thread(System.Threading.ThreadStart)'和   'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)'

  1. 你如何消除代码的歧义才能运行它? 回答(错过括号。无论如何,这不是原来的主要问题)
  2. 另外,我还没有完全掌握() =>指向/应用的空列表在哪里?
  3. 好吧,“你可以将任意数量的参数传递给方法”的方法是什么?
  4. 如何通过空列表理解(任意数量)参数的传递?
  5. 更新(解决Jon Skeet的评论):
    不,我不会被C#2困住。

    the previous passage相同的问题:

    ==========报价开头:
    将参数传递给线程的目标方法的最简单方法是执行一个lambda表达式,该表达式使用所需的参数调用该方法:

    static void Main()
    {
      Thread t = new Thread ( () => Print ("Hello from t!") );
      t.Start();
    }
    
    static void Print (string message) 
    {
      Console.WriteLine (message);
    }
    

    使用这种方法,您可以向该方法传入任意数量的参数。“

    ===============报价结束

    UPDATE2:
    most complete answer is IMO by @Lee虽然我标记为正确的另一个答案,猜测我立即回答的问题是什么 - 如何把一些东西放在空括号中(我已经害怕通过列表或参数调用它)< / p>

4 个答案:

答案 0 :(得分:3)

您需要明确说明参数列表:

new Thread
(delegate()
  {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
   }
).Start();

delegate关键字允许您定义anonymous method。 Lambda表达式(即使用() => { ... }语法)类似,但使用delegate可以省略参数列表。在这种情况下,这是不明确的,因为Thread有两个构造函数,它们采用不同的委托类型。一个ThreadStart定义为

delegate void ThreadStart();

,另一个采用ParameterizedThreadStart,定义为:

delegate void ParameterizedThreadStart(object state);

由于您省略了参数列表,因此编译器不知道您正在使用哪种委托类型。

我假设“任意数量的参数”是由您的委托关闭的变量。例如,您可以:

string message = "This is so easy!";
var thread = new Thread(delegate() {
    Console.WriteLine(message);
});
thread.Start();

您可以使用ParameterizedThreadStart将任意对象传递给线程委托,例如

public class ThreadData {
   //properties to pass to thread
}

ThreadData data = new ThreadData { ... }
Thread thread = new Thread((object state) => {
    ThreadData data = (ThreadData)state;
});

thread.Start(data);

答案 1 :(得分:2)

delegate之后需要括号来指定参数,在这种情况下没有参数:

new Thread(
  delegate() {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
  }
).Start();

作者正在讨论的“任意数量的参数”是您可以使用在单独线程中运行的代码中创建委托的范围内的数据,而不必将数据传递给{{ 1}}方法:

Start

实际发生的是变量不再是方法中的局部变量,而是自动存储在闭包中,委托与定义它的方法共享。

只要你只想启动一个线程,这就行得很好。如果要启动使用不同数据的多个线程,您可以将数据传递到string msg1 = "I'm running on another thread!"; string msg2 = "This is so easy!"; new Thread( delegate() { Console.WriteLine(msg1); Console.WriteLine(msg2); } ).Start(); 方法,也可以创建一个可以保存数据的类,将线程的代码放在类中,然后创建一个实例对于你开始的每个线程。

答案 2 :(得分:1)

为了解决模糊调用,可以添加空括号(委托将被视为ThreadStart委托):

new Thread(delegate() {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
}).Start();

或添加状态参数(委托将被视为ParametrizedThreadStart)它可以工作,但它很奇怪,因为你不需要那个参数。

new Thread(delegate(object state) {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
}).Start();

或将代理人转为ThreadStart

new Thread((ThreadStart)delegate {
    Console.WriteLine("I'm running on another thread!");
    Console.WriteLine("This is so easy!");
}).Start();

答案 3 :(得分:1)

() =>不是C#中的空列表。在上下文中,它在本书中使用,它是lambda表达式的开始。 ()表示此表达式不带参数。