国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 編程 > C# > 正文

C#實現向多線程傳參的三種方式實例分析

2020-01-24 01:23:23
字體:
來源:轉載
供稿:網友

本文實例講述了C#實現向多線程傳參的三種方式。分享給大家供大家參考,具體如下:

從《C#高級編程》了解到給線程傳遞參數有兩種方式,一種方式是使用帶ParameterizedThreadStart委托參數的Thread構造函數,另一種方式是創建一個自定義類,把線程的方法定義為實例的方法,這樣就可以初始化實例的數據,之后啟動線程。

方式一:使用ParameterizedThreadStart委托

如果使用了ParameterizedThreadStart委托,線程的入口必須有一個object類型的參數,且返回類型為void。且看下面的例子:

using System;using System.Threading;namespace ThreadWithParameters{  class Program  {    static void Main(string[] args)    {      string hello = "hello world";      //這里也可簡寫成Thread thread = new Thread(ThreadMainWithParameters);      //但是為了讓大家知道這里用的是ParameterizedThreadStart委托,就沒有簡寫了      Thread thread = new Thread(new ParameterizedThreadStart(ThreadMainWithParameters));      thread.Start(hello);      Console.Read();    }    static void ThreadMainWithParameters(object obj)    {      string str = obj as string;      if(!string.IsNullOrEmpty(str))        Console.WriteLine("Running in a thread,received: {0}", str);    }  }}

這里稍微有點麻煩的就是ThreadMainWithParameters方法里的參數必須是object類型的,我們需要進行類型轉換。為什么參數必須是object類型呢,各位看看ParameterizedThreadStart委托的聲明就知道了。

public delegate void ParameterizedThreadStart(object obj);   //ParameterizedThreadStart委托的聲明

方式二:創建自定義類

定義一個類,在其中定義需要的字段,將線程的主方法定義為類的一個實例方法,說得不是很明白,還是看實際的例子吧。

using System;using System.Threading;namespace ThreadWithParameters{  public class MyThread  {    private string data;    public MyThread(string data)    {      this.data = data;    }    public void ThreadMain()    {      Console.WriteLine("Running in a thread,data: {0}", data);    }  }  class Program  {    static void Main(string[] args)    {      MyThread myThread = new MyThread("hello world");      Thread thread = new Thread(myThread.ThreadMain);      thread.Start();      Console.Read();    }  }}

對這種方法也不是很滿意,總不能一遇到比較耗時的方法,就新建一個類吧。。。

那有什么更好辦法即不用強制類型轉換,也不用新建一個類呢?

下面就介紹下我無意中找到的一個方法,具體是在哪見過的我也不記得了,罪過啊。。

方式三:使用匿名方法

using System;using System.Threading;namespace ThreadWithParameters{  class Program  {    static void Main(string[] args)    {      string hello = "hello world";      //如果寫成Thread thread = new Thread(ThreadMainWithParameters(hello));這種形式,編譯時就會報錯      Thread thread = new Thread(() => ThreadMainWithParameters(hello));      thread.Start();      Console.Read();    }    static void ThreadMainWithParameters(string str)    {       Console.WriteLine("Running in a thread,received: {0}", str);    }  }}

哇,你會發現既不用類型強制轉換也不用新建類就運行成功了。

但是為什么這種方式能行呢,根據昨天 @亂舞春秋 的提示,我也用ildasm反編譯了一下,確實如他所說,我所謂的第三種方式其實和第二種方式是一樣的,只不過自定義類編譯器幫我們做了。

下面的是第三種方式main方法反編譯的IL代碼:

.method private hidebysig static void Main(string[] args) cil managed{  .entrypoint  // 代碼大小    51 (0x33)  .maxstack 3  .locals init ([0] class [mscorlib]System.Threading.Thread thread,       [1] class ThreadWithParameters.Program/'<>c__DisplayClass1' 'CS$<>8__locals2')  IL_0000: newobj   instance void ThreadWithParameters.Program/'<>c__DisplayClass1'::.ctor()  IL_0005: stloc.1  IL_0006: nop  IL_0007: ldloc.1  IL_0008: ldstr   "hello world"  IL_000d: stfld   string ThreadWithParameters.Program/'<>c__DisplayClass1'::hello  IL_0012: ldloc.1  IL_0013: ldftn   instance void ThreadWithParameters.Program/'<>c__DisplayClass1'::'<Main>b__0'()  IL_0019: newobj   instance void [mscorlib]System.Threading.ThreadStart::.ctor(object, native int)  IL_001e: newobj   instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ThreadStart)  IL_0023: stloc.0  IL_0024: ldloc.0  IL_0025: callvirt  instance void [mscorlib]System.Threading.Thread::Start()  IL_002a: nop  IL_002b: call    int32 [mscorlib]System.Console::Read()  IL_0030: pop  IL_0031: nop  IL_0032: ret} // end of method Program::Main

在看看第二種方式的IL代碼:

.method private hidebysig static void Main(string[] args) cil managed{  .entrypoint  // 代碼大小    44 (0x2c)  .maxstack 3  .locals init ([0] class ThreadWithParameters.MyThread myThread,       [1] class [mscorlib]System.Threading.Thread thread)  IL_0000: nop  IL_0001: ldstr   "hello world"  IL_0006: newobj   instance void ThreadWithParameters.MyThread::.ctor(string)  IL_000b: stloc.0  IL_000c: ldloc.0  IL_000d: ldftn   instance void ThreadWithParameters.MyThread::ThreadMain()  IL_0013: newobj   instance void [mscorlib]System.Threading.ThreadStart::.ctor(object, native int)  IL_0018: newobj   instance void [mscorlib]System.Threading.Thread::.ctor(class [mscorlib]System.Threading.ThreadStart)  IL_001d: stloc.1  IL_001e: ldloc.1  IL_001f: callvirt  instance void [mscorlib]System.Threading.Thread::Start()  IL_0024: nop  IL_0025: call    int32 [mscorlib]System.Console::Read()  IL_002a: pop  IL_002b: ret} // end of method Program::Main

比較兩端代碼,可以發現兩者都有一個newobj,這句的作用是初始化一個類的實例,第三種方式由編譯器生成了一個類:c__DisplayClass1

IL_0000: newobj   instance void ThreadWithParameters.Program/'<>c__DisplayClass1'::.ctor()IL_0006: newobj   instance void ThreadWithParameters.MyThread::.ctor(string)

注意:簡單并不一定是好事,匿名方法容易造成不易察覺的錯誤

希望本文所述對大家C#程序設計有所幫助。

發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 彝良县| 秦皇岛市| 房山区| 新绛县| 延吉市| 岑溪市| 垣曲县| 聊城市| 乌拉特中旗| 美姑县| 镇雄县| 营口市| 宣武区| 双江| 金湖县| 察哈| 五指山市| 闵行区| 乡城县| 区。| 三明市| 雅安市| 乌恰县| 海伦市| 余姚市| 辰溪县| 汉中市| 洛扎县| 邹平县| 绿春县| 镇平县| 凌海市| 萨嘎县| 禹州市| 缙云县| 施甸县| 修武县| 东阳市| 长治县| 渭源县| 渭源县|