關於多執行緒和非同步程式設計簡單來說,就是多執行緒並行執行任務提速,非同步程式設計等待不浪費資源,併發集合確保資料訪問安全,三者合力提升程式效率與反應能力。
1. 理解執行緒
想象一下,你在廚房做飯,同時需要洗菜、切菜、炒菜。如果你一個人來做,就需要在這些任務之間來回切換,這很慢。但如果請幾個朋友幫忙,每人負責一項任務,大家同時工作,效率就高多了。這裡的“朋友”就像是計算機中的“執行緒”。
執行緒就是計算機程式中執行任務的最小單位。一個程式預設啟動時只有一個主執行緒,但可以透過建立額外的執行緒來同時執行多個任務,這就是多執行緒。
示例程式碼:
using System;
using System.Threading;
class MultiThreadingDemo
{
static void Main()
{
// 這是主執行緒
Console.WriteLine("主執行緒開始");
// 建立並啟動一個新的執行緒
Thread thread = new Thread(DoWork);
thread.Start();
Console.WriteLine("主執行緒繼續做其他事情");
// 等待新執行緒完成(非必須,這裡為了演示)
thread.Join();
Console.WriteLine("所有任務完成,主執行緒結束");
}
static void DoWork()
{
Console.WriteLine("新執行緒開始執行任務");
Thread.Sleep(2000); // 模擬耗時操作
Console.WriteLine("新執行緒任務完成");
}
}
註釋說明:這段程式碼中,Main
方法所在的執行緒是主執行緒,它建立了一個新執行緒DoWork
去執行一個耗時任務。Thread.Sleep(2000)
模擬了這個耗時操作,讓新執行緒暫停2秒,期間主執行緒可以繼續執行其他任務。
2. Task和非同步程式設計模型(async和await)
有時候,我們不希望直接管理執行緒,而是希望程式自動為我們處理併發問題。這時候,就可以使用.NET
提供的Task
和async/await
關鍵字。
想象你在等待外賣,你可以選擇一直站在門口等(阻塞),也可以繼續做其他事,聽到門鈴響再去拿(非同步)。async/await
就是讓你的程式在等待某些耗時操作(如網路請求)時,可以去做別的事,不浪費時間。
示例程式碼:
using System;
using System.Threading.Tasks;
class AsyncDemo
{
static async Task Main()
{
Console.WriteLine("開始下載檔案");
// 非同步下載檔案,不會阻塞主執行緒
await DownloadFileAsync();
Console.WriteLine("檔案下載完成");
}
static async Task DownloadFileAsync()
{
// 模擬檔案下載耗時操作
await Task.Delay(2000);
Console.WriteLine("檔案下載中...");
}
}
註釋說明:DownloadFileAsync
方法模擬了檔案下載,使用Task.Delay(2000)
模擬耗時操作。await
關鍵字讓呼叫它的方法(這裡是Main
方法)在等待時可以“放手”,去做其他事情,直到DownloadFileAsync
完成才繼續往下執行。
3. 併發集合和執行緒安全
當你在多執行緒環境下訪問和修改共享資料時,可能會遇到資料不一致的問題,這叫做“競態條件”。為了解決這個問題,.NET
提供了執行緒安全的集合,比如ConcurrentDictionary
。
想象你和朋友同時編輯一份購物清單,如果不小心同時新增了同樣的物品,就會出錯。執行緒安全的集合就像每個人都有自己的筆,在寫之前先確認沒人同時寫,保證清單的正確性。
示例程式碼:
using System.Collections.Concurrent;
using System.Threading.Tasks;
class ThreadSafeCollectionsDemo
{
static ConcurrentDictionary<string, int> shoppingList = new ConcurrentDictionary<string, int>();
static async Task AddItemAsync(string item)
{
// 嘗試新增或更新數量,執行緒安全
shoppingList.AddOrUpdate(item, 1, (key, oldValue) => oldValue + 1);
await Task.Yield(); // 模擬一點點耗時,讓併發效果更明顯
}
static async Task Main()
{
var tasks = new Task[10];
for (int i = 0; i < 10; i++)
{
tasks[i] = AddItemAsync("蘋果");
}
await Task.WhenAll(tasks);
foreach (var item in shoppingList)
{
Console.WriteLine($"{item.Key}: {item.Value}");
}
}
}
註釋說明:這段程式碼展示瞭如何使用ConcurrentDictionary
來安全地在多執行緒環境下新增購物清單項。即使多個執行緒同時嘗試新增“蘋果”,AddOrUpdate
方法也會確保不會有重複計數的問題。
總結:
-
多執行緒入門:執行緒是程式執行任務的基本單位,多執行緒允許程式同時執行多個任務,如同廚房裡多位廚師同時準備不同菜餚,顯著提升工作效率。透過建立和管理執行緒,你能使程式執行更加流暢,響應更快。
-
非同步程式設計與Task:
async
和await
關鍵字是C#中非同步程式設計的核心,它們使程式能在等待耗時操作(如網路請求、磁碟I/O)時釋放當前執行緒去做其他工作,如同等待外賣時可以繼續做家務,不白白浪費時間,從而最佳化程式的整體效能。 -
併發集合與執行緒安全:在多執行緒環境中,直接訪問共享資料可能導致資料不一致性問題。
ConcurrentDictionary
等併發集合為此而生,它們內建同步機制,確保了多執行緒訪問時的資料安全,有效避免了競態條件,讓資料操作既高效又可靠。
這些知識點相互支撐,構成了處理併發問題、提升程式效率與穩定性的堅實基礎。掌握它們,你就能在編寫高質量、高效能應用程式的道路上邁出重要一步。