多線程之線程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent
介紹
重新想象 Windows 8 Store Apps 之 線程同步
Semaphore - 訊號量
CountdownEvent - 通過訊號數量實現線程同步
Barrier - 屏障
ManualResetEvent - 手動紅綠燈
AutoResetEvent - 自動紅綠燈
樣本
1、示範 Semaphore 的使用
Thread/Lock/SemaphoreDemo.xaml
<Page x:Class="XamlDemo.Thread.Lock.SemaphoreDemo" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:local="using:XamlDemo.Thread.Lock" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d"> <Grid Background="Transparent"> <StackPanel Margin="120 0 0 0"> <TextBlock Name="lblMsg" FontSize="14.667" /> </StackPanel> </Grid></Page>
Thread/Lock/SemaphoreDemo.xaml.cs
/* * 示範 Semaphore 的使用 * * Semaphore - 訊號量 * SemaphoreSlim - 輕量級的 Semaphore * * 註: * 直譯 Semaphore 的話不太好理解,可以將 Semaphore 理解為一個許可證中心,該許可證中心的許可證數量是有限的 * 線程想要執行就要先從許可證中心擷取一個許可證(如果許可證中心的許可證已經發完了,那就等著,等著其它線程歸還許可證),執行完了再還回去 */ using System;using System.Collections.Generic;using System.Threading;using System.Threading.Tasks;using Windows.UI.Xaml.Controls;using Windows.UI.Xaml.Navigation; namespace XamlDemo.Thread.Lock{ public sealed partial class SemaphoreDemo : Page { /* * Semaphore(int initialCount, int maximumCount, string name) * initialCount - 許可證中心初始擁有的許可證數量,即初始情況下已經發出的許可證數量為maximumCount - initialCount * maximumCount - 許可證中心總共擁有的許可證數量 * name - 許可證中心的名稱 * Semaphore OpenExisting(string name) - 開啟指定名稱的許可證中心 */ // 執行個體化一個許可證中心,該中心擁有的許可證數量為 2 個 private Semaphore _semaphore = new Semaphore(2, 2); public SemaphoreDemo() { this.InitializeComponent(); } protected async override void OnNavigatedTo(NavigationEventArgs e) { List<Task> tasks = new List<Task>(); // 類比 5 個線程並存執行,拿到許可證的線程才能運行,而許可證中心只有 2 個許可證 for (int i = 0; i < 5; i++) { CancellationToken token = new CancellationTokenSource().Token; Task task = Task.Run( () => { OutMsg(string.Format("task {0} 等待一個許可證", Task.CurrentId)); token.WaitHandle.WaitOne(5000); // WaitOne() - 申請許可證 _semaphore.WaitOne(); OutMsg(string.Format("task {0} 申請到一個許可證", Task.CurrentId)); token.WaitHandle.WaitOne(1000); OutMsg(string.Format("task {0} 歸還了一個許可證", Task.CurrentId)); // int Release() - 歸還許可證,傳回值為:Release() 之前許可證中心可用的許可證數量 int ignored = _semaphore.Release(); // int Release(int releaseCount) - 指定釋放的訊號量的次數(按本文的理解就是指定歸還的許可證數量) }, token); tasks.Add(task); } await Task.WhenAll(tasks); } private void OutMsg(string msg) { var ignored = Dispatcher.RunAsync( Windows.UI.Core.CoreDispatcherPriority.High, () => { lblMsg.Text += msg; lblMsg.Text += Environment.NewLine; }); } }}