ThreadPool.QueueUserWorkItem with a lambda express

2020-02-23 06:08发布

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:

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.

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.

5条回答
SAY GOODBYE
2楼-- · 2020-02-23 06:16

It's a nice way of doing it. I don't see any disadvantages of using lambdas. It's simple and clean.

查看更多
smile是对你的礼貌
3楼-- · 2020-02-23 06:23

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.

查看更多
相关推荐>>
4楼-- · 2020-02-23 06:25

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.

查看更多
Rolldiameter
5楼-- · 2020-02-23 06:28

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
    }
}
查看更多
Lonely孤独者°
6楼-- · 2020-02-23 06:35

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.

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.

查看更多
登录 后发表回答