總體來說多線程中向線程傳遞參數有3種方式
- 創建對象,初始化對象中的一些值,然后在Start()方法中調用該對象方法
- 通過lambda表達式
- Thread.Start方法
先看代碼:
static void Count(object iterations) { CountNumbers((int)iterations); } static void CountNumbers(int iterations) { for (int i = 1; i <= iterations; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine("{0} prints {1}", Thread.CurrentThread.Name, i); } } static void PrintNumber(int number) { Console.WriteLine(number); } class ThreadSample { private readonly int _iterations; public ThreadSample(int iterations) { _iterations = iterations; } public void CountNumbers() { for (int i = 1; i <= _iterations; i++) { Thread.Sleep(TimeSpan.FromSeconds(0.5)); Console.WriteLine("{0} prints {1}", Thread.CurrentThread.Name, i); } } }
static void Main(string[] args) {
//首先創建了ThreadSample類的一個對象,並提供了一個迭代次數 var sample = new ThreadSample(10);
(1)第一種方式.自定義類的方式 //使用ThreadSample對象的CountNumbers方法啟動線程
//該方法運行在另一個線程中,但是使用數字10,該數字是通過ThreadSample對象的構造函數傳入的 var threadOne = new Thread(sample.CountNumbers);(我們只是使用相同的間接方式將該迭代次數傳遞給另一個線程) threadOne.Name = "ThreadOne"; threadOne.Start(); threadOne.Join(); Console.WriteLine("--------------------------");
(2)第二種方式:使用Thread.Start方法,這種方式object只能傳單個參數
//另一種傳遞數據的方式是使用Thread.Start方法(為了應用該方法,在線程中啟動的方法必須接受object類型的單個參數) var threadTwo = new Thread(Count); threadTwo.Name = "ThreadTwo"; threadTwo.Start(8); threadTwo.Join(); Console.WriteLine("--------------------------");
(3)第三種方式:使用lambda表達式。lambda表達式定義了一個不屬於任何類的方法
//我們創建了一個方法,該方法使用需要的參數調用了另一個方法,並在另一個線程中運行該方法 var threadThree = new Thread(() => CountNumbers(12)); threadThree.Name = "ThreadThree"; threadThree.Start(); threadThree.Join(); Console.WriteLine("--------------------------");
//當在lambda表達式中使用任何局部變量時, C#會生成一個類,並將該變量作為該類的一個屬性。所以實際上該方式與 threadOne線程中使用的一樣,但是我們無須定義該類, C#編譯器會自動幫我們實現
//這也會導致一個問題,如果在多個lambda表達式中使用相同的變量,它們會共享該變量值
//它們都會打印20,因為在這兩個線程啟動之前變量被修改為20。 int i = 10; var threadFour = new Thread(() => PrintNumber(i)); i = 20; var threadFive = new Thread(() => PrintNumber(i)); threadFour.Start(); threadFive.Start(); Console.Read(); }
運行結果:
對代碼的分析和總結:
當主程序啟動時,首先創建了ThreadSample類的一個對象,並提供了一個迭代次數。然后使用該對象的CountNumbers方法啟動線程。該方法運行在另一個線程中,但是使用數字10,該數字是通過ThreadSample對象的構造函數傳入的。因此,我們只是使用相同的間接方式將該迭代次數傳遞給另一個線程。
另一種傳遞數據的方式是使用Thread.Start方法。該方法會接收一個對象,並將該對象,傳遞給線程。為了應用該方法,在線程中啟動的方法必須接受object類型的單個參數。在創建threadTwo線程時演示了該方式。我們將8作為一個對象傳遞給了Count方法,然后 Count方法被轉換為整型。
接下來的方式是使用lambda表達式。lambda表達式定義了一個不屬於任何類的方法。我們創建了一個方法,該方法使用需要的參數調用了另一個方法,並在另一個線程中運行該方法。當啟動threadThree線程時,打印出了12個數字,這正是我們通過lambda表達式傳遞,的數字。
使用lambda表達式引用另一個C#對象的方式被稱為閉包。當在lambda表達式中使用任何局部變量時, C#會生成一個類,並將該變量作為該類的一個屬性。所以實際上該方式與 threadOne線程中使用的一樣,但是我們無須定義該類, C#編譯器會自動幫我們實現。
這可能會導致幾個問題。例如,如果在多個lambda表達式中使用相同的變量,它們會共享該變量值。在前一個例子中演示了這種情況。當啟動threadFour和threadFive線程時,.它們都會打印20,因為在這兩個線程啟動之前變量被修改為20。

