简体   繁体   English

ThreadPool.QueueUserWorkItem,带有lambda表达式和匿名方法

[英]ThreadPool.QueueUserWorkItem with a lambda expression and anonymous method

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. 另一种方法是创建一个实现具有3个成员的不可变类型的新类:test,s1和s2。 That just seems like extra work with no benefit at this point. 这似乎是额外的工作,在这一点上没有任何好处。

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. 它创建了一个类来保存捕获的变量(test,s1和s2),并将委托实例传递给lambda,lambda将转换为匿名类的方法。 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. 换句话说,如果您继续使用替代方案,那么最终会得到与编译器为您生成的内容非常相似的东西。

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. 您传递到另一个线程的状态是完全包含的,并且所涉及的类型都没有任何线程关联问题。

It's a nice way of doing it. 这是一个很好的方式。 I don't see any disadvantages of using lambdas. 我没有看到使用lambdas的任何缺点。 It's simple and clean. 它简单而干净。

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. 虽然字符串是不可变的,但对它们(或任何变量)的引用不是。

One potential problem with the pattern is that it's very tempting 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
    }
}

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

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