C# 带有 lambda 表达式和匿名方法的 ThreadPool.QueueUserWorkItem
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/738139/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
ThreadPool.QueueUserWorkItem with a lambda expression and anonymous method
提问by Scott Whitlock
Passing two parameters to a new thread on the threadpool can sometimes be complicated, but it appears that with lambda expressions and anonymous methods, I can do this:
将两个参数传递给线程池上的新线程有时可能很复杂,但似乎使用 lambda 表达式和匿名方法,我可以这样做:
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
}
Now, I've certainly simplified this example, but these points are key:
现在,我当然简化了这个例子,但以下几点是关键:
- The string objects being passed are immutable and therefore threadsafe
- The s1 and s2 variables are declared within the scope of the try block, which I exit immediately after queuing the work to the thread pool, so the s1 and s2 variables are never modified after that.
- 传递的字符串对象是不可变的,因此是线程安全的
- s1 和 s2 变量在 try 块的范围内声明,我在将工作排队到线程池后立即退出,因此在此之后永远不会修改 s1 和 s2 变量。
Is there something wrong with this?
这有什么问题吗?
The alternative is to create a new class that implements an immutable type with 3 members: test, s1, and s2. That just seems like extra work with no benefit at this point.
另一种方法是创建一个新类,该类实现了具有 3 个成员的不可变类型:test、s1 和 s2。在这一点上,这似乎是额外的工作,没有任何好处。
采纳答案by chuckj
There is nothing wrong with this. The compiler is essentially doing automatically what you described as your alternative. It creates a class to hold the captured variables (test, s1 and s2) and passes a delegate instance to the lambda which is turned into a method on the anonymous class. In other words, if you went ahead with your alternative you would end up with soemthing very similar to what the compiler just generated for you.
这没有任何问题。编译器本质上是自动执行您所描述的替代方法。它创建一个类来保存捕获的变量(test、s1 和 s2),并将委托实例传递给 lambda,该实例变成匿名类上的方法。换句话说,如果你继续你的选择,你最终会得到与编译器刚刚为你生成的非常相似的东西。
回答by Mehrdad Afshari
It's a nice way of doing it. I don't see any disadvantages of using lambdas. It's simple and clean.
这是一个很好的方法。我没有看到使用 lambda 的任何缺点。它简单而干净。
回答by JaredPar
For this particular example, no there is nothing wrong here. The state you've passed into the other thread is wholely contained and none of the types involve have any thread affinity issues.
对于这个特定的例子,这里没有任何问题。您传递给另一个线程的状态被完全包含在内,并且所涉及的任何类型都没有任何线程关联问题。
回答by casperOne
What you are looking at is refered to as a closure. As chuckj states, the compiler is generating a class at compile time which corresponds to the members that are accessed outside of the closure.
您正在查看的内容称为闭包。正如chuckj 所说,编译器在编译时生成一个类,该类对应于在闭包外部访问的成员。
The only thing you have to worry about is if you have ref or out parameters. While strings are immutable, the references to them (or any variable) are NOT.
您唯一需要担心的是您是否有 ref 或 out 参数。虽然字符串是不可变的,但对它们(或任何变量)的引用不是。
回答by Joel Coehoorn
One potential problem with the pattern is that it's verytempting to expand it into something more-generic but less-safe like this (scratch code- don't expect it to work):
该模式的一个潜在问题是,很容易将其扩展为更通用但更不安全的东西,例如(临时代码 - 不要指望它起作用):
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
}
}