C#支持經過多線程並行地執行代碼,一個線程有它獨立的執行路徑,可以與其它的線程同時地運行。一個C#程序開始於一個單線程,這個單線程是被CLR和操做系統(也稱爲「主線程」)自動建立的,並具備多線程建立額外的線程。
除非被指定,不然全部的例子都假定如下命名空間被引用了:git
using System; using System.Threading;
C#開啓線程的方法有:github
總的來講其實線程的開啓基本都涉及到委託的使用。c#
首先來看一個比較簡單的例子,採用第一種開啓線程的方法——異步委託多線程
using System; using System.Threading; namespace Study { class Program { static void test() { Console.WriteLine("TestThread"); } static void Main(string[] args) { Action a = test; a.BeginInvoke(null, null); Console.WriteLine("MainThread"); Console.ReadLine(); } } }
編譯運行,發現結果與預期有所不一樣。結果以下圖
若是按着逐行運行代碼的方式,那麼應該是先輸出TestThread,可是結果倒是先輸出MainThread。
將a.BeginInvoke(null,null);
和Console.WriteLine("MainThread");
對調位置以後,結果和以前的依然一致。這就說明,異步委託開啓的線程是和主線程同時同步進行的。
Action委託是指向一個沒有返回值的函數,那麼假設一個線程,咱們須要取得他的返回結果並輸出,那麼就要用到Func委託。
看下面的源碼異步
using System; using System.Threading; namespace SummerStudy { class Program { static string test(int i, string str) { Console.WriteLine("TestThread" + "\t參數i是:" + i); return str; } static void Main(string[] args) { Func<int, string, string> a = test; IAsyncResult res = a.BeginInvoke(1, "返回值", null, null); string o = a.EndInvoke(res); Console.WriteLine("MainThread\t" + "線程返回值是:" + o); Console.ReadLine(); } }
同時異步委託開啓線程中,判斷線程是否結束的方法也有兩種,一種是利用IAsyncResult的IsCompleted方法,一種是使用方法進行線程結束判斷。
具體使用方法以下。函數
IAsyncResult ia = a.BeginInvoke() if(ia.IsCompleted == false) { //GoOn }
IAsyncResult ia = a.BeginInvoke() ia.AsyncWaitHandle.WaitOne(Time);//Time爲等待時間,超時後纔會運行下一行代碼,未完成直接跳出返回false
或者經過自定義方法,BeginInvoke中倒數第二個參數是一個委託,傳遞一個函數,在線程結束以後會自動的調用。spa
static string Test(int a) { } Func<int, string> a = Test; IAsyncResult ia = a.BeginInvoke(100, CallBack, a); static void CallBack(IAsyncResult ar) { Func<int, string> a = ia.AsyncState as Func<int, string>; string res = a.EndInvoke(ar); }
在使用Lambda表達式做爲委託的時候,最後一個參數能夠爲空,由於Lambda表達式能夠訪問外部變量。操作系統
使用Thread類建立一個實例,它的構造方法中須要傳遞一個委託。經過委託綁定線程。
直接上代碼線程
using System; using System.Threading; namespace Study { class Program { static void test() { Console.WriteLine("Thread"); Thread.Sleep(2000); Console.WriteLine("TimeOver"); } static void Main(string[] args) { Thread t = new Thread(test); t.Start(); Console.WriteLine("Main"); Console.Read(); } } }
對於須要傳遞參數的委託,則必須制定參數類型爲object,在線程Start方法中傳遞參數code
namespace SummerStudy { class Program { static void test(object c) { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Thread,\t線程id爲" + id + ",\t參數是:" + c); Thread.Sleep(2000); Console.WriteLine("TimeOver"); } static void Main(string[] args) { Thread t = new Thread(test); t.Start("xxx.avi"); Console.WriteLine("Main"); Console.Read(); } } }
固然你也能夠自定義一個類,在類中自定義數據傳遞。
這種方法有助於節省時間,具體使用方法以下
using System; using System.Threading; namespace SummerStudy { class Program { static void test(object c) { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Thread,\t線程id爲" + id + ",\t參數是:" + c); Thread.Sleep(2000); Console.WriteLine("TimeOver"); } static void Main(string[] args) { ThreadPool.QueueUserWorkItem(test, "asfasf"); Console.Read(); } } }
其中委託必需要有一個參數,不管是否使用該參數。且只適用於使用時間短的線程,不能改變優先級
使用Task類開啓線程,還有TaskFactory建立
Task類實例
using System; using System.Threading; using System.Threading.Tasks; namespace SummerStudy { class Program { static void test(object c) { int id = Thread.CurrentThread.ManagedThreadId; Console.WriteLine("Thread,\t線程id爲" + id); Thread.Sleep(2000); Console.WriteLine("TimeOver"); } static void Main(string[] args) { Task t = new Task(test, "Asfgasg"); t.Start(); //或者 TaskFactory tf = new TaskFactory(); Task t1 = tf.StartNew(test); Console.Read(); } } }
個人掘金:WarrenRyan
個人簡書:WarrenRyan
歡迎關注個人博客得到第一時間更新 https://blog.tity.xyz
個人Github:WarrenRyan
個人博客園:WarrenRyan