Question

What is the difference between the two pieces of code below? Will there be any issues using the second one?

Scenario 1:

private void Log(Exception e)
{
    ThreadPool.QueueUserWorkItem(new WaitCallback(Log), e);
}

private void Log(object obj)
{
    Exception e = (Exception)obj;
    Logger.Log(e);
}

Scenario 2

private void Log(Exception e)
{
    ThreadPool.QueueUserWorkItem(
        (obj) => 
            {
                Logger.Log(e);
            });
}

In scenario 2, I am not passing the exception in as a paramter to the ThreadPool. How does the thread marshalling of the exception object occur? Will there be any problems? What are the limitations of doing this if any? The big advantage is that you can pass in any number of parameters very easily.

Was it helpful?

Solution

The only difference is that in scenario two you are closing over the e variable which effectively moves the stack variable e into a custom type that is moved to the heap so you don't lose it.

I think this ought to work fine.

Edit: As for performance, no there ought not to be a significant difference between the two scenarios. In scenario 1 you are already passing the exception as state to the QueueUserWorkItem method which internally moves that exception reference onto the heap. The only overhead is that when you use a closure is that the compiler creates a type for you and stores any captured variables as fields on that type.

OTHER TIPS

Just to note, instead of the Lambda, you could do the same with an anonymous method, and it would also work in C# 2.0:

ThreadPool.QueueUserWorkItem(delegate(Object e) 
    { 
        Logger.Log(e as Exception); 
    });
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top