揭秘C#線程通信:從互斥鎖到消息傳遞,一篇就夠了!
在C#中,線程之間的通信是實現(xiàn)多線程應用程序的關鍵環(huán)節(jié)。線程通信不僅確保數(shù)據(jù)的安全性和一致性,還是實現(xiàn)多線程協(xié)作和同步的重要手段。本文將帶你深入了解C#中線程通信的多種方式,并通過實例代碼展示其應用。
1. 互斥鎖(Mutex)和監(jiān)視器(Monitor)
互斥鎖和監(jiān)視器是C#中實現(xiàn)線程同步的基本機制。它們可以防止多個線程同時訪問共享資源,從而避免數(shù)據(jù)競爭和不一致。
示例代碼:使用Monitor實現(xiàn)線程同步
public class Counter
{
private int _count = 0;
public void Increment()
{
Monitor.Enter(this);
try
{
_count++;
Console.WriteLine($"Count: {_count} by thread {Thread.CurrentThread.ManagedThreadId}");
}
finally
{
Monitor.Exit(this);
}
}
}
// 使用示例
var counter = new Counter();
Task.Run(() => counter.Increment());
Task.Run(() => counter.Increment());
2. 信號量(Semaphore)和信號量Slim(SemaphoreSlim)
信號量和信號量Slim用于控制對共享資源的訪問數(shù)量。它們允許多個線程同時訪問資源,但會限制訪問的最大數(shù)量。
示例代碼:使用SemaphoreSlim限制并發(fā)訪問
public class ResourcePool
{
private SemaphoreSlim _semaphore = new SemaphoreSlim(3); // 限制最大3個線程同時訪問
public async Task AccessResourceAsync()
{
await _semaphore.WaitAsync(); // 等待信號量可用
try
{
// 訪問共享資源
Console.WriteLine($"Accessing resource by thread {Thread.CurrentThread.ManagedThreadId}");
await Task.Delay(1000); // 模擬耗時操作
}
finally
{
_semaphore.Release(); // 釋放信號量
}
}
}
// 使用示例
var pool = new ResourcePool();
var tasks = Enumerable.Range(1, 10).Select(i => pool.AccessResourceAsync()).ToArray();
await Task.WhenAll(tasks);
3. 線程間消息傳遞
在C#中,可以通過多種方式實現(xiàn)線程間的消息傳遞,如使用QueueUserWorkItem、ThreadPool、BlockingCollection或Channel等。
示例代碼:使用BlockingCollection進行線程間消息傳遞
public class MessageProducerConsumer
{
private BlockingCollection<string> _messages = new BlockingCollection<string>();
public void StartProducer()
{
Task.Run(() =>
{
for (int i = 0; i < 10; i++)
{
_messages.Add($"Message {i}"); // 生產(chǎn)消息
Thread.Sleep(500); // 模擬耗時操作
}
_messages.CompleteAdding(); // 表示不再添加消息
});
}
public void StartConsumer()
{
Task.Run(() =>
{
foreach (var message in _messages.GetConsumingEnumerable())
{
Console.WriteLine($"Consumed: {message} by thread {Thread.CurrentThread.ManagedThreadId}");
}
});
}
}
// 使用示例
var producerConsumer = new MessageProducerConsumer();
producerConsumer.StartProducer();
producerConsumer.StartConsumer();
4. 事件(Event)和委托(Delegate)
事件和委托是C#中實現(xiàn)線程間解耦通信的有效方式。事件允許一個線程通知其他線程發(fā)生了某個特定的動作或狀態(tài)變化。
示例代碼:使用事件和委托進行線程通信
public class DataProvider
{
public event Action<string> DataAvailable; // 定義一個事件
public void SimulateDataGeneration()
{
for (int i = 0; i < 5; i++)
{
string data = $"Data {i}";
DataAvailable?.Invoke(data); // 觸發(fā)事件
Thread.Sleep(1000); // 模擬耗時操作
}
}
}
public class DataConsumer
{
public void ConsumeData(string data)
{
Console.WriteLine($"Consumed data: {data} by thread {Thread.CurrentThread.ManagedThreadId}");
}
}