本文小編為大家詳細介紹“C#怎么實現多線程編程”,內容詳細,步驟清晰,細節處理妥當,希望這篇“C#怎么實現多線程編程”文章能幫助大家解決疑惑,下面跟著小編的思路慢慢深入,一起來學習新知識吧。
1、可以使用線程將代碼同其他代碼隔離,提高應用程序的可靠性。
2、可以使用線程來簡化編碼。
3、可以使用線程來實現并發執行。
1、進程與線程:進程作為操作系統執行程序的基本單位,擁有應用程序的資源,進程包含線程,進程的資源被線程共享,線程不擁有資源。
2、前臺線程和后臺線程:通過Thread類新建線程默認為前臺線程。當所有前臺線程關閉時,所有的后臺線程也會被直接終止,不會拋出異常。
3、掛起(Suspend)和喚醒(Resume):由于線程的執行順序和程序的執行情況不可預知,所以使用掛起和喚醒容易發生死鎖的情況,在實際應用中應該盡量少用。
4、阻塞線程:Join,阻塞調用線程,直到該線程終止。
5、終止線程:Abort:拋出 ThreadAbortException 異常讓線程終止,終止后的線程不可喚醒。Interrupt:拋出 ThreadInterruptException 異常讓線程終止,通過捕獲異??梢岳^續執行。
6、線程優先級:Highest AboveNormal Normal BelowNormal Lowest ,默認為Normal。
線程函數通過委托傳遞,可以不帶參數,也可以帶參數(只能有一個參數),可以用一個類或結構體封裝參數。
案例:
class Program { static void Main(string[] args) { Thread t1 = new Thread(new ThreadStart(TestMethod));//創建無參數數線程 Thread t2 = new Thread(new ParameterizedThreadStart(TestMethod));//創建帶參數的線程 //設置為后臺進程 t1.IsBackground = true; t2.IsBackground = true; t1.Start(); t2.Start("hello"); Console.ReadKey(); } public static void TestMethod() { Console.WriteLine("不帶參數的線程函數"); } //參數要定義為object 類型 public static void TestMethod(object data) { string datastr = data as string; Console.WriteLine("帶參數的線程函數,參數為:{0}", datastr); } }
由于線程的創建和銷毀需要耗費一定的開銷,過多的使用線程會造成內存資源的浪費,出于對性能的考慮,于是引入了線程池的概念。線程池維護一個請求隊列,線程池的代碼從隊列提取任務,然后委派給線程池的一個線程執行,線程執行完不會被立即銷毀,這樣既可以在后臺執行任務,又可以減少線程創建和銷毀所帶來的開銷。
線程池線程默認為后臺線程(IsBackground)。
class Program { static void Main(string[] args) { //將工作項加入到線程池隊列中,這里可以傳遞一個線程參數 ThreadPool.QueueUserWorkItem(TestMethod, "Hello"); Console.ReadKey(); } //線程函數 public static void TestMethod(object data) { string datastr = data as string; Console.WriteLine(datastr); } }
使用ThreadPool的QueueUserWorkItem()方法發起一次異步的線程執行很簡單,但是該方法最大的問題是沒有一個內建的機制讓你知道操作什么時候完成,有沒有一個內建的機制在操作完成后獲得一個返回值。為此,可以使用System.Threading.Tasks中的Task類。
構造一個Task<TResult>對象,并為泛型TResult參數傳遞一個操作的返回類型。
class Program { static void Main(string[] args) { Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000); t.Start(); t.Wait(); Console.WriteLine(t.Result); Console.ReadKey(); } private static Int32 Sum(Int32 n) { Int32 sum = 0; for (; n > 0; --n) checked{ sum += n;} //結果太大,拋出異常 return sum; } }
一個任務完成時,自動啟動一個新任務。
一個任務完成后,它可以啟動另一個任務,下面重寫了前面的代碼,不阻塞任何線程。
class Program { static void Main(string[] args) { Task<Int32> t = new Task<Int32>(n => Sum((Int32)n), 1000); t.Start(); //t.Wait(); Task cwt = t.ContinueWith(task => Console.WriteLine("The result is {0}", t.Result)); Console.ReadKey(); } private static Int32 Sum(Int32 n) { Int32 sum = 0; for (; n > 0; --n) checked { sum += n; } //結果溢出,拋出異常 return sum; } }
委托的異步調用:BeginInvoke() 和 EndInvoke()
namespace Test { public delegate string MyDelegate(object data); class Program { static void Main(string[] args) { MyDelegate mydelegate = new MyDelegate(TestMethod); IAsyncResult result = mydelegate.BeginInvoke("Thread Param", TestCallback, "Callback Param"); //異步執行完成 string resultstr = mydelegate.EndInvoke(result); } //線程函數 public static string TestMethod(object data) { string datastr = data as string; Console.WriteLine(datastr); return datastr; } //異步回調函數 public static void TestCallback(IAsyncResult data) { Console.WriteLine(data.AsyncState); } } }
異步回調函數在上面線程函數執行結束后,將要退出時執行。
讀到這里,這篇“C#怎么實現多線程編程”文章已經介紹完畢,想要掌握這篇文章的知識點還需要大家自己動手實踐使用過才能領會,如果想了解更多相關內容的文章,歡迎關注億速云行業資訊頻道。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。