簡體   English   中英

帶有Lambda語法的C#匿名線程

[英]C# Anonymous Thread with Lambda Syntax

一般來說,我得到了C#的lambda語法。 但是匿名線程語法對我來說並不完全清楚。 有人可以解釋這樣的線程創建實際上在做什么嗎? 請盡可能詳細,我希望能夠逐步實現讓這項工作變得神奇的魔力。

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

我真的不明白的部分是Thread(() => ...

當我使用這種語法時,似乎我刪除了傳統ThreadStart的許多限制,例如必須在沒有參數的方法上調用。

謝謝你的幫助!

() => ...只是意味着lambda表達式不帶參數。 您的示例等效於以下內容:

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

// ...

new Thread(worker).Start();

lambda中的{ ... }允許你在lambda體中使用多個語句,通常你只允許表達式。

這個:

() => 1 + 2

相當於:

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

由於在我開始之前有一些答案,我將寫下額外的參數如何進入lambda。

簡而言之,這個東西叫做封閉 讓我們用new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start();剖析你的例子new Thread(() => _Transaction_Finalize_Worker(transId, machine, info, newConfigPath)).Start(); 成為碎片。

對於閉包,類的字段和局部變量之間存在差異。 因此,我們假設transId是類字段(因此可以通過this.transId訪問),而其他只是局部變量。

在幕后如果在類編譯器中使用lambda創建具有不可描述名稱的嵌套類,為了簡單起見,我們將其命名為X ,並將所有局部變量放在那里。 它也在那里寫lambda,所以它成為常規方法。 然后編譯器重寫您的方法,以便它在某個時刻創建XnewConfigPathx.machinex.infox.newConfigPath替換對machineinfonewConfigPath訪問。 X接收參考this ,所以λ-方法可以訪問transId經由parentRef.transId

嗯,它非常簡化但接近現實。


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
}

這是在C#中創建線程的匿名方式,它只是啟動線程(因為你使用的是Start();)以下2種方法是等效的。 如果你需要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();

現在是Thread方法的一部分。 如果你看到Thread聲明,我們有以下內容(我省略了3個其他聲明)。

public Thread(ThreadStart start);

線程將委托作為參數。 委托是指方法。 所以Thread接受一個委托參數。 ThreadStart聲明如下。

public delegate void ThreadStart();

這意味着您可以將任何方法傳遞給Thread,它返回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();

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM