>>返回《C# 并发编程》html
同步的类型主要有两种: 通讯和数据保护。编程
class LockClass { // 这个锁会保护 _value。 private readonly object _mutex = new object(); private int _value; public void Increment() { lock (_mutex) { _value = _value + 1; } } }
锁的使用,有四条重要的规则。并发
class SemaphoreSlimClass { // 这个锁保护 _value。 private readonly SemaphoreSlim _mutex = new SemaphoreSlim(1); private int _value; public async Task DelayAndIncrementAsync() { await _mutex.WaitAsync(); try { var oldValue = _value; await Task.Delay(TimeSpan.FromSeconds(oldValue)); _value = oldValue + 1; } finally { _mutex.Release(); } } }
规则在这里也一样适用异步
- 限制锁的做用范围。
- 文档中写清锁保护的内容。
- 锁范围内的代码尽可能少。
- 在控制锁的时候毫不运行随意的代码
class ManualResetEventSlimClass { private readonly ManualResetEventSlim _initialized = new ManualResetEventSlim(); private int _value; public int WaitForInitialization() { _initialized.Wait(); return _value; } public void InitializeFromAnotherThread() { _value = 13; _initialized.Set(); } }
若是 ManualResetEventSlim
不能知足需求,还可考虑用 AutoResetEvent
、 CountdownEvent
或 Barrier
async
比喻:url
ManualResetEventSlim
的整个工做方法有点像人群经过大门AutoResetEvent
事件像一个旋转门,一次只容许一人经过。class TaskCompletionSourceClass { private readonly TaskCompletionSource<object> _initialized = new TaskCompletionSource<object>(); private int _value1; private int _value2; public async Task<int> WaitForInitializationAsync() { await _initialized.Task; return _value1 + _value2; } public void Initialize() { _value1 = 13; _value2 = 17; _initialized.TrySetResult(null); } }
信号是一种通用的通知机制code
class MaxDegreeClass { //工做流限流 IPropagatorBlock<int, int> DataflowMultiplyBy2() { var options = new ExecutionDataflowBlockOptions { MaxDegreeOfParallelism = 10 }; return new TransformBlock<int, int>(data => data * 2, options); } // 使用 PLINQ IEnumerable<int> ParallelMultiplyBy2(IEnumerable<int> values) { return values.AsParallel() .WithDegreeOfParallelism(10) .Select(item => item * 2); } // 使用 Parallel 类 void ParallelRotateMatrices(IEnumerable<Action<float>> matrices, float degrees) { var options = new ParallelOptions { MaxDegreeOfParallelism = 10 }; Parallel.ForEach(matrices, options, matrix => matrix.Invoke(degrees)); } //并发性异步代码能够用 SemaphoreSlim 来限流: async Task<string[]> DownloadUrlsAsync( IEnumerable<string> urls) { var httpClient = new HttpClient(); var semaphore = new SemaphoreSlim(10); var tasks = urls.Select(async url => { await semaphore.WaitAsync(); try { return await httpClient.GetStringAsync(url); } finally { semaphore.Release(); } }).ToArray(); return await Task.WhenAll(tasks); } }