简体   繁体   English

带有Lambda语法的C#匿名线程

[英]C# Anonymous Thread with Lambda Syntax

In general I get C#'s lambda syntax. 一般来说,我得到了C#的lambda语法。 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(() => ... 我真的不明白的部分是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. 当我使用这种语法时,似乎我删除了传统ThreadStart的许多限制,例如必须在没有参数的方法上调用。

Thanks for your help! 谢谢你的帮助!

() => ... just means that the lambda expression takes no parameters. () => ...只是意味着lambda表达式不带参数。 Your example is equivalent to the following: 您的示例等效于以下内容:

void worker()
{
    DoLongRunningWork();
    MessageBox.Show("Long Running Work Finished!");
}

// ...

new Thread(worker).Start();

The { ... } in the lambda let you use multiple statements in the lambda body, where ordinarily you'd only be allowed an expression. lambda中的{ ... }允许你在lambda体中使用多个语句,通常你只允许表达式。

This: 这个:

() => 1 + 2

Is equivalent to: 相当于:

() => { return (1 + 2); }

As there was some answers before I started, I will just write about how additional parameters make their way into lambda. 由于在我开始之前有一些答案,我将写下额外的参数如何进入lambda。

In short this thing called closure . 简而言之,这个东西叫做封闭 Lets dissect your example with new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start(); 让我们用new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start();剖析你的例子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. 因此,我们假设transId是类字段(因此可以通过this.transId访问),而其他只是局部变量。

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. 在幕后如果在类编译器中使用lambda创建具有不可描述名称的嵌套类,为了简单起见,我们将其命名为X ,并将所有局部变量放在那里。 Also it writes lambda there, so it becomes normal method. 它也在那里写lambda,所以它成为常规方法。 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. 然后编译器重写您的方法,以便它在某个时刻创建XnewConfigPathx.machinex.infox.newConfigPath替换对machineinfonewConfigPath访问。 Also X receives reference to this , so lambda-method could access transId via parentRef.transId . X接收参考this ,所以λ-方法可以访问transId经由parentRef.transId

Well, it is extremely simplified but near to reality. 嗯,它非常简化但接近现实。


UPD: 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
}

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. 这是在C#中创建线程的匿名方式,它只是启动线程(因为你使用的是Start();)以下2种方法是等效的。 If you need Thread variable to do something (for example block the calling thread by calling thread0.join()), then you use the 2nd one. 如果你需要Thread变量来做某事(例如通过调用thread0.join()阻塞调用线程),那么你使用第二个。

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. 现在是Thread方法的一部分。 If you see the Thread declaration we have the following (I omitted 3 others). 如果你看到Thread声明,我们有以下内容(我省略了3个其他声明)。

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. 所以Thread接受一个委托参数。 ThreadStart is declared like this. ThreadStart声明如下。

public delegate void ThreadStart();

It means you can pass any method to Thread which return void and doesn't take any parameters. 这意味着您可以将任何方法传递给Thread,它返回void并且不接受任何参数。 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. 现在我们认为ThreadMethod方法做的很少,我们可以将它设置为本地和匿名。 So we don't need the ThreadMethod method at all. 所以我们根本不需要ThreadMethod方法。

    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(). 在委托之后看到最后一个花括号等同于我们的ThreadMethod()。 You can further shorten the previous code by introducing Lambda statement (See MSDN). 您可以通过引入Lambda语句进一步缩短以前的代码(请参阅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();

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

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