C# Anonymous Thread with Lambda Syntax

71,576

Solution 1

This is anonymous way to create a thread in C# which just start the thread (because you are using Start();) Following 2 ways are equivalent. If you need Thread variable to do something (for example block the calling thread by calling thread0.join()), then you use the 2nd one.

new Thread(() =>
{
    Console.WriteLine("Anonymous Thread job goes here...");
}).Start();

var thread0=  new Thread(() =>
{
    Console.WriteLine("Named Thread job goes here...");
});
thread0.Start();

Now the Thread method part. If you see the Thread declaration we have the following (I omitted 3 others).

public Thread(ThreadStart start);

Thread takes a delegate as a parameter. Delegate is reference to a method. So Thread takes a parameter which is a delegate. ThreadStart is declared like this.

public delegate void ThreadStart();

It means you can pass any method to Thread which return void and doesn't take any parameters. So following examples are equivalent.

ThreadStart del = new ThreadStart(ThreadMethod);
var thread3 = new Thread(del);
thread3.Start();

ThreadStart del2 = ThreadMethod;
var thread4 = new Thread(del2);
thread4.Start();

var thread5 = new Thread(ThreadMethod);
thread5.Start();

//This must be separate method
public static void ThreadMethod()
{
    Console.WriteLine("ThreadMethod doing important job...");
}

Now we think that ThreadMethod method is doing little work we can make it to local and anonymous. So we don't need the ThreadMethod method at all.

    new Thread( delegate () 
    {
        Console.WriteLine("Anonymous method Thread job goes here...");
    }).Start();

You see after delegate to last curly braces is equivalent to our ThreadMethod(). You can further shorten the previous code by introducing Lambda statement (See MSDN). This is just you are using and see how it has been ended up like the following.

new Thread( () =>
{
    Console.WriteLine("Lambda statements for thread goes here...");
}).Start();

Solution 2

As there was some answers before I started, I will just write about how additional parameters make their way into lambda.

In short this thing called closure. Lets dissect your example with new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start(); into pieces.

For closure there's a difference between class' fields and local variables. Thus let's assume that transId is class field (thus accessible through this.transId) and others are just local variables.

Behind the scenes if lambda used in a class compiler creates nested class with unspeakable name, lets name it X for simplicity, and puts all local variables there. Also it writes lambda there, so it becomes normal method. Then compiler rewrites your method so that it creates X at some point and replaces access to machine, info and newConfigPath with x.machine, x.info and x.newConfigPath respectively. Also X receives reference to this, so lambda-method could access transId via parentRef.transId.

Well, it is extremely simplified but near to reality.


UPD:

class A
{
    private int b;

    private int Call(int m, int n)
    {
        return m + n;
    }

    private void Method()
    {
        int a = 5;
        a += 5;
        Func<int> lambda = () => Call(a, b);
        Console.WriteLine(lambda());
    }

    #region compiler rewrites Method to RewrittenMethod and adds nested class X
    private class X
    {
        private readonly A _parentRef;
        public int a;

        public X(A parentRef)
        {
            _parentRef = parentRef;
        }

        public int Lambda()
        {
            return _parentRef.Call(a, _parentRef.b);
        }
    }

    private void RewrittenMethod()
    {
        X x = new X(this);
        x.a += 5;
        Console.WriteLine(x.Lambda());
    }
    #endregion
}
Share:
71,576
jocull
Author by

jocull

Specializing in Java, JVM, JavaScript, TypeScript, Node.js, Git, Linux, and Docker.

Updated on October 30, 2020

Comments

  • jocull
    jocull about 3 years

    In general I get C#'s lambda syntax. However the anonymous thread syntax isn't completely clear to me. Can someone explain what a thread creation like this is actually doing? Please be as detailed as possible, I'd love to have a sort of step-by-step on the magic that makes this work.

    (new Thread(() => {
            DoLongRunningWork();
            MessageBox.Show("Long Running Work Finished!");
        })).Start();
    

    The part that I really don't understand is the Thread(() => ...

    When I use this syntax it seems like I remove a lot of the limits of a traditional ThreadStart such as having to invoke on a method that has no parameters.

    Thanks for your help!