.NET異步程序設計——給線程傳遞數據


shanzm-2021年8月24日 19:51:26

0. 前情說明:

首先我們都知道,創建一個線程執行一個無參函數,則方式如下:

//期望在線程中執行的函數
static void Do()
{
    Console.WriteLine("Create Thread");
}

//創建線程執行函數
static void Main(string[] ars)
{
    Thread thread=new Thread(Do);
    thread.Start();
    Console.ReadKey();
}

若是我們希望開新線程執行一個帶有參數的方法,則上面的語句就無法執行了。

上面的Thread類構造函數Thread()在.NET中是有四重重載的。

上面使用的Thread對象的構造函數的參數類型是ThreadStart委托類型



1. ParameterizedThreadStart類型的委托

1.1 簡單示例及說明

使用以ParameterizedThreadStart類型的委托為參數的Thread對象構造函數,並使用Thread.Start()來傳遞參數

Thread()方法在.net中有四個重載,我們可以使用其參數類型為ParameterizedThreadStart委托的構造函數,實現線程中執行帶參數的函數,即往線程中傳遞數據。

注意:

  • 是使用Thread.Start(object param)傳遞參數的

  • ParameterizedThreadStart委托是:

    • 參數只能是一個
    • 參數類型是object類型
    • 無返回值的
  • 因為ParameterizedThreadStart委托的參數類型是object類型,所以我們需要修改期望在新線程中行的方法,將其參數改為object類型,在方法中使用時在進行拆箱

示例:

static void Do(object obj)
{
    int n = (int)obj;
    Console.WriteLine($"方法1:新開線程執行方法,其參數是{n}");
}
static void Main(string[] args)
{
    Thread thread = new Thread(Do);//這里的Do函數就是ParameterizedThreadStart類型的委托
    int n = 999;
    thread.Start(n);//在Start函數中傳遞參數
}

1.2 多參並獲取返回值

程序自然面向對象,我們可以定義一個輔助類(注意不能使用結構體,結構體為值類型)

//臨時輔助類
class TempClass
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Ret { get; set; }
}
//期望在新線程中執行的函數,並期望獲取對參數操作的結果
static void DoWithParam(object obj)
{
    TempClass tempClass = obj as TempClass;
    tempClass.Ret = tempClass.X + tempClass.Y;
}
//創建線程並執行
static void Main(string[] args)
{
    Thread thread = new Thread(DoWithParam);
    TempClass tempClass = new TempClass() { X = 1, Y = 2 };
    thread.Start(tempClass);
    thread.Join();//注意這里等待thread線程執行完成
    Console.WriteLine($"實現獲取到返回值:{tempClass.Ret}");
}


2. 使用自定義類

2.1 簡單示例及說明

將方法封裝在類中,則在自定義類實例化的時候,實現傳遞參數

這里我們依舊是使用Thread對象的參數類型為ThreadStart類型的構造函數,但是我們需要在新線程中執行的有參函數封裝在一個類中
在類的實例化時,實現傳遞參數

示例:

有一個期望在新線程中執行的有參函數如下

pubic void Do(string param)
{
    Console.WriteLine($"新開線程執行方法,其參數是{param}");
}

我們可以這樣封裝該方法,並在創建線程並執行該方法

//自定義類
public class MyClass
{
    public int param { get; set; }
    public void Do()
    {
        Console.WriteLine($"方法2:新開線程執行方法,其參數是{param}");
    }
}
//創建線程並執行
static void Main(string[] args)
{
    MyClass myClass=new MyClass(999);
    Thread thread =new Thread(myClass.Do);
}

2.2 獲取返回值

思路一樣,在自定義類中添加一個屬性,作為返回值

class TempClass2
{
    public int X { get; set; }
    public int Y { get; set; }
    public int Ret { get; set; }
    public void DoWithParam()
    {
        Ret = X + Y;
    }
}
static void Main(string[] args)
{
    TempClass2 tempClass2 = new TempClass2() { X = 1, Y = 2 };
    Thread thread = new Thread(tempClass2.DoWithParam);
    thread.Start();
    thread.Join();//注意這里表示tempClass線程執行完成
    Console.WriteLine($"實現獲取到返回值:{tempClass2.Ret}");
}



3. 使用Lambda表達式

使用Lambda表達式調用期望在新線程中執行的函數

這是目前最方便的往線程中傳遞數據的方案

示例:

//期望在新線程中執行的方法
static void Do(int n, int m)
{
    Console.WriteLine(n * m);
}

static void Main(string[] args)
{
    Thread thread1 = new Thread(() => Do(2, 3));//定義一個Lambda表達式,調用Do()函數
    thread1.Start();

    //其實這里我們就是可以將所有的函數邏輯直接寫在Lambda表達式中,從而更加方便
    Thread thread2 = new Thread(() => { Console.WriteLine(2 * 3); });
    thread2.Start();
}


4. 參考以及文中源代碼下載


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM