Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/oop/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
具有Lambda语法的C#匿名线程_C#_Multithreading_Lambda - Fatal编程技术网

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

具有Lambda语法的C#匿名线程,c#,multithreading,lambda,C#,Multithreading,Lambda,一般来说,我得到C#的lambda语法。然而,匿名线程语法对我来说并不完全清楚。有人能解释一下这样的线程创建实际上在做什么吗?请尽可能详细,我很想有一个魔术,使这项工作的一步一步 (new Thread(() => { DoLongRunningWork(); MessageBox.Show("Long Running Work Finished!"); })).Start(); 我真正不理解的部分是线程(()=>… 当我使用这种语法时,我似乎消除

一般来说,我得到C#的lambda语法。然而,匿名线程语法对我来说并不完全清楚。有人能解释一下这样的线程创建实际上在做什么吗?请尽可能详细,我很想有一个魔术,使这项工作的一步一步

(new Thread(() => {
        DoLongRunningWork();
        MessageBox.Show("Long Running Work Finished!");
    })).Start();
我真正不理解的部分是
线程(()=>…

当我使用这种语法时,我似乎消除了传统
ThreadStart
的许多限制,例如必须在没有参数的方法上调用

感谢您的帮助!

()=>…
只是表示lambda表达式不带参数。您的示例等效于以下内容:

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

// ...

new Thread(worker).Start();
lambda中的
{…}
允许在lambda主体中使用多个语句,通常只允许使用一个表达式

这:

相当于:

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

因为在我开始之前有一些答案,所以我将只写一些附加参数是如何进入lambda的

简而言之,这就是所谓的闭包。让我们用
新线程(()=>_Transaction\u Finalize\u Worker(transId、machine、info、newConfigPath)).Start();
将您的示例分解成几部分

对于闭包,类的字段和局部变量之间存在差异。因此,让我们假设
transId
是类字段(因此可以通过
this.transId
)访问),而其他字段只是局部变量

在幕后,如果类编译器中使用的lambda创建了具有无法说出的名称的嵌套类,为了简单起见,让它命名为
X
,并将所有局部变量放在那里。它也在那里写入lambda,因此它成为普通方法。然后编译器重写您的方法,以便在某个点创建
X
,并替换对
的访问>machine
info
newConfigPath
分别与
x.machine
x.info
x.newConfigPath
一起使用。另外
x
接收对
的引用,因此lambda方法可以通过
parentRef.transId
访问
transId

嗯,它非常简单,但接近现实


UPD:

A类
{
私人INTB;
专用整数呼叫(整数m,整数n)
{
返回m+n;
}
私有无效方法()
{
INTA=5;
a+=5;
Func lambda=()=>调用(a,b);
Console.WriteLine(lambda());
}
#区域编译器将方法重写为RewritenMethod并添加嵌套类X
私人X类
{
私有只读A_parentRef;
公共INTA;
公共X(A parentRef)
{
_parentRef=parentRef;
}
公共int Lambda()
{
返回parentRef.Call(a,parentRef.b);
}
}
私有无效重写方法()
{
X X=新X(本);
x、 a+=5;
Console.WriteLine(x.Lambda());
}
#端区
}

这是一种匿名方法,可以在C#中创建一个只启动线程的线程(因为您使用的是start();) 以下两种方法是等效的。如果您需要线程变量来执行某些操作(例如,通过调用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();
现在是线程方法部分。如果您看到线程声明,我们有以下内容(我省略了其他3个)

线程将委托作为参数。委托是对方法的引用。因此线程将接受一个作为委托的参数。ThreadStart声明如下

public delegate void ThreadStart();
这意味着您可以将任何方法传递给返回void且不接受任何参数的线程

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...");
}
现在我们认为ThreadMethod方法所做的工作很少,我们可以将其设置为本地和匿名。因此,我们根本不需要ThreadMethod方法

    new Thread( delegate () 
    {
        Console.WriteLine("Anonymous method Thread job goes here...");
    }).Start();
您可以看到,委托给最后一个花括号后的代码相当于我们的ThreadMethod()。您可以通过引入Lambda语句(请参见MSDN)进一步缩短前面的代码。这就是您正在使用的代码,并可以看到它是如何结束的,如下所示

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

它创建一个新的线程对象,传入一个匿名方法(委托),并启动它。仅此而已。创建匿名方法本质上是一种将代码块作为委托参数传递的方法,这一部分对我来说很有意义,但我也可以这样做:
new thread(()=>\u Transaction\u Finalize\u Worker(transId,machine,info,newConfigPath)).Start();
-为什么我现在可以传入所有这些参数?因为lambda表达式可以从外部作用域捕获变量。看看闭包:我想这是最令人困惑的部分。我不明白lambda是如何突然允许访问外部作用域变量的。除了“这就是它的方式”之外,还有什么别的吗?这是一项让您能够以更具表现力和功能性的方式进行编程的功能。如果您不想,您不必将lambdas用作闭包,但它们有时会派上用场。@jocull我在回答中试图描述lambdas是如何在C#中工作的。谢谢,我想我知道现在发生了什么-很多匿名类型的魔法!
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...");
}
    new Thread( delegate () 
    {
        Console.WriteLine("Anonymous method Thread job goes here...");
    }).Start();
new Thread( () =>
{
    Console.WriteLine("Lambda statements for thread goes here...");
}).Start();