简体   繁体   English

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

[英]How to “pass in any number of arguments to the method” of a thread through lambda expression?

I follow Passing Data to a Thread of "PART 1: GETTING STARTED" of "Threading in C#" by Joseph Albahari. 我遵循约瑟夫·阿尔巴哈里(Joseph Albahari)将数据传递到线程 “ C#中的线程 ”的“部分1:入门”的线程中。

Namely the passage: 即段落:

====== Start of quote ======报价开始

" With this approach, you can pass in (to where?) any number of arguments to the method . You can even wrap the entire implementation in a multi-statement lambda: 通过这种方法,您可以将任意数量的参数传递(到哪里?) 。您甚至可以将整个实现包装在多语句lambda中:

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

You can do the same thing almost as easily in C# 2.0 with anonymous methods: 您可以使用匿名方法在C#2.0中几乎一样轻松地完成相同的操作:

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

============ End of quote ============报价结束

That is, I've tried the "easily" as: 也就是说,我尝试将“轻松”作为:

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

but it produces the error: 但是会产生错误:

The call is ambiguous between the following methods or properties: 'System.Threading.Thread.Thread(System.Threading.ThreadStart)' and 'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)' 下列方法或属性之间的调用不明确:'System.Threading.Thread.Thread(System.Threading.ThreadStart)'和'System.Threading.Thread.Thread(System.Threading.ParameterizedThreadStart)'

  1. How can you disambiguate the code in order to run it? 您如何区分代码以便运行它? Answered (missed parenthesis. Anyway, it wasn't the original main question) 已回答(缺少括号。无论如何,这不是最初的主要问题)
  2. Also, I did not quite grasp where is the empty list () => directed/applied to? 另外,我不太了解空列表() =>指向/应用于何处?
  3. A well as, what is the method to which " you can pass in any number of arguments to the method"? 还有,“可以向该方法传递任意数量的参数”的方法是什么?
  4. How to understand the passing of (any number of) arguments through the empty list? 如何理解通过空列表传递(任意数量的)参数?

Update (addressing Jon Skeet's comment): 更新 (解决乔恩·斯基特的评论):
No, I am not stuck with C# 2. 不,我不喜欢C#2。

The same question(s) to the previous passage : 上一段相同的问题:

========== Start of quote: ==========报价开始:
" The easiest way to pass arguments to a thread's target method is to execute a lambda expression that calls the method with the desired arguments: 将参数传递给线程的目标方法的最简单方法是执行一个lambda表达式,该表达式使用所需的参数调用该方法:

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

With this approach, you can pass in any number of arguments to the method." 通过这种方法,您可以将任意数量的参数传递给该方法。”

=============== End of quote ==============报价结束

Update2: 更新2:
The most complete answer is IMO by @Lee though I marked as correct another answer for guessing to answer at once what I have not even originally asked - how to put something in empty parenthesis (I'm already afraid to call it by list or by arguments) 最完整的答案是@Lee的IMO,尽管我标记为正确的另一个答案是想立即回答我什至没有问到的问题-如何将某些内容放在空括号中(我已经很害怕按列表或按名称参数)

You need to make the argument list explicit: 您需要使参数列表明确:

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

The delegate keyword allows you to define an anonymous method . delegate关键字允许您定义匿名方法 Lambda expressions (ie using the () => { ... } syntax) are similar, however using delegate allows you to omit the parameter list. Lambda表达式(即,使用() => { ... }语法)相似,但是使用delegate可以省略参数列表。 This is ambiguous in this case, since there are two constructors for Thread which take different delegate types. 在这种情况下,这是不明确的,因为Thread有两个构造函数采用不同的委托类型。 One takes a ThreadStart which is defined as 一个采用ThreadStart ,其定义为

delegate void ThreadStart();

and the other takes a ParameterizedThreadStart which is defined as: 另一个采用ParameterizedThreadStart ,其定义为:

delegate void ParameterizedThreadStart(object state);

Since you are omitting the parameter list, the compiler does not know which delegate type you are using. 由于省略了参数列表,因此编译器不知道您使用的是哪种委托类型。

I assume the "any number of arguments" are variables which are closed-over by your delegate. 我假设“任意数量的参数”是由您的代表封闭的变量。 For example you could have: 例如,您可能有:

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

You can use a ParameterizedThreadStart to pass an arbitrary object to your thread delegate eg 您可以使用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);

You need the parentheses after delegate to specify the parameters, in this case no parameters: 您需要在delegate后的括号中指定参数,在这种情况下,无需参数:

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

The "any number of arguments" that the author is talking about is that you can use data from the scope where the delegate is created inside the code that runs in a separate thread, without having to pass the data to the Start method: 作者在谈论的“任意数量的参数”是,您可以使用在单独的线程中运行的代码内创建委托的范围内的数据,而不必将数据传递给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();

What's actually happening is that the variables are no longer local variables in the method, instead they are automatically stored in a closure, which the delegate shares with the method where it is defined. 实际情况是变量不再是方法中的局部变量,而是自动存储在闭包中,委托与定义该方法的方法共享该闭包。

This works well as long as you only want to start one thread. 只要您只想启动一个线程,此方法就可以很好地工作。 If you want to start multiple threads that uses different data, you would either pass the data into the Start method or create a class that can hold the data, put the code for the thread in the class, and create one instance for each thread that you start. 如果要启动使用不同数据的多个线程,则可以将数据传递到Start方法中,或者创建一个可以保存数据的类,将该线程的代码放入该类中,并为每个线程创建一个实例。你先来。

In order to resolve ambiguous call, you can add empty parentheses (delegate will be treated as ThreadStart delegate): 为了解决歧义调用,您可以添加空括号(该委托将被视为ThreadStart委托):

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

Or add state parameter (delegate will be treated as ParametrizedThreadStart) It works, but it's odd, because you don't need that parameter. 或添加状态参数(代理将被视为ParametrizedThreadStart)。它可以工作,但是很奇怪,因为您不需要该参数。

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

Or cast delegate to ThreadStart 或将委托转换为ThreadStart

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

() => isn't an empty list in C#. () =>在C#中不是一个空列表。 In the context it is used in the book it is the start of a lambda expression. 在上下文中,它是lambda表达式的开始。 The () means that this expression takes no arguments. ()表示此表达式不带参数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM