[源码下载]

重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent

作者:webabcd

介绍
重新想象 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(, ); public SemaphoreDemo()
{
this.InitializeComponent();
} protected async override void OnNavigatedTo(NavigationEventArgs e)
{
List<Task> tasks = new List<Task>(); // 模拟 5 个线程并行执行,拿到许可证的线程才能运行,而许可证中心只有 2 个许可证
for (int i = ; i < ; i++)
{
CancellationToken token = new CancellationTokenSource().Token; Task task = Task.Run(
() =>
{
OutMsg(string.Format("task {0} 等待一个许可证", Task.CurrentId));
token.WaitHandle.WaitOne(); // WaitOne() - 申请许可证
_semaphore.WaitOne();
OutMsg(string.Format("task {0} 申请到一个许可证", Task.CurrentId)); token.WaitHandle.WaitOne(); 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;
});
}
}
}

2、演示 CountdownEvent 的使用
Thread/Lock/CountdownEventDemo.xaml

<Page
x:Class="XamlDemo.Thread.Lock.CountdownEventDemo"
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/CountdownEventDemo.xaml.cs

/*
* 演示 CountdownEvent 的使用
*
* CountdownEvent - 通过信号数量实现线程同步
*/ 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 CountdownEventDemo : Page
{
private static int _count; public CountdownEventDemo()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
// 初始信号数量为 100 个
using (CountdownEvent countdown = new CountdownEvent())
{
// AddCount(), AddCount(int signalCount) - 增加 1 个信号,或增加指定数量的信号
// Reset(), Reset(int count) - 重置为初始的信号数量,或重置为指定的信号数量
// Signal(), Signal(int signalCount) - 减少 1 个信号,或减少指定数量的信号
// CurrentCount - 获取当前的信号数量 for (int i = ; i < ; i++)
{
Task task = Task.Run(
() =>
{
Interlocked.Increment(ref _count);
// 减少 1 个信号
countdown.Signal();
});
} // 阻塞当前线程,直到 CountdownEvent 的信号数量变为 0
countdown.Wait(); lblMsg.Text = "count: " + _count.ToString();
}
}
}
}

3、演示 Barrier 的使用
Thread/Lock/BarrierDemo.xaml

<Page
x:Class="XamlDemo.Thread.Lock.BarrierDemo"
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/BarrierDemo.xaml.cs

/*
* 演示 Barrier 的使用
*
* Barrier - 屏障
*
* 按如下方式理解:
* 1、Participant - 参与者
* 2、SignalAndWait() - 某一个参与者已经到达屏障了
* 3、所有参与者都到达屏障后,屏障解除
*/ using System.Threading;
using System.Threading.Tasks;
using Windows.UI.Core;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Thread.Lock
{
public sealed partial class BarrierDemo : Page
{
private static int _count; public BarrierDemo()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
// AddParticipant(), AddParticipants(int participantCount) - 增加 1 个参与者,或增加指定数量的参与者
// RemoveParticipant(), RemoveParticipants(int participantCount) - 减少 1 个参与者,或减少指定数量的参与者
// ParticipantCount - 获取参与者总数
// ParticipantsRemaining - 尚未到达屏障的参与者总数 Barrier barrier = new Barrier(
, // 初始有 5 个参与者
(ctx) => // 屏障解除之后
{
var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.High,
() =>
{
lblMsg.Text = "count: " + _count.ToString();
});
}); for (int i = ; i < ; i++)
{
Task task = Task.Run(
() =>
{
Interlocked.Increment(ref _count);
// 某一个参与者已经到达屏障了
barrier.SignalAndWait();
// SignalAndWait(int millisecondsTimeout) - 指定一个超时时间
// SignalAndWait(CancellationToken cancellationToken) - 指定一个 CancellationToken
});
}
}
}
}

4、演示 ManualResetEvent 的使用
Thread/Lock/ManualResetEventDemo.xaml

<Page
x:Class="XamlDemo.Thread.Lock.ManualResetEventDemo"
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/ManualResetEventDemo.xaml.cs

/*
* 演示 ManualResetEvent 的使用
*
* ManualResetEvent - 手动红绿灯
* ManualResetEventSlim - 轻量级的 ManualResetEvent
*/ using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.System.Threading;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Thread.Lock
{
public sealed partial class ManualResetEventDemo : Page
{
// true - 指定初始状态为绿灯
private ManualResetEvent _manualResetEvent = new ManualResetEvent(true); private static int _count = ; public ManualResetEventDemo()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
ManualResetEvent sleep = new ManualResetEvent(false); Task tas = Task.Run(
() =>
{
while (true)
{
// WaitOne() - 判断:绿灯则进入,红灯则阻塞
_manualResetEvent.WaitOne(); /*
* WaitOne(1000)
* 1、如果当前是绿灯则进入
* 2、如果当前是红灯则阻塞
* a) 1000 毫秒之内收到 Set() 信号则进入
* b) 1000 毫秒之后如果还没收到 Set() 信号则强行进入
*/ IAsyncAction ignored = Windows.System.Threading.ThreadPool.RunAsync(
(threadPoolWorkItem) =>
{
// 在当前线程 sleep 1000 毫秒(WinRT 中没有 Thread.Sleep() 了)
sleep.WaitOne(); OutMsg(string.Format("count:{0}, time:{1}", ++_count, DateTime.Now.ToString("mm:ss"))); // Set() - 发出绿灯信号,并设置为绿灯
_manualResetEvent.Set(); },
WorkItemPriority.High); // Reset() - 发出红灯信号,并设置为红灯
_manualResetEvent.Reset();
}
});
} private void OutMsg(string msg)
{
var ignored = Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.High,
() =>
{
lblMsg.Text = msg;
});
}
}
}

5、演示 AutoResetEvent 的使用
Thread/Lock/AutoResetEventDemo.xaml

<Page
x:Class="XamlDemo.Thread.Lock.AutoResetEventDemo"
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/AutoResetEventDemo.xaml.cs

/*
* 演示 AutoResetEvent 的使用
*
* AutoResetEvent - 自动红绿灯
*
* AutoResetEvent 和 ManualResetEvent 的区别在于:AutoResetEvent 在 WaitOne() 进入之后会自动 Reset()
*/ using System;
using System.Threading;
using System.Threading.Tasks;
using Windows.Foundation;
using Windows.System.Threading;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Navigation; namespace XamlDemo.Thread.Lock
{
public sealed partial class AutoResetEventDemo : Page
{
// true - 指定初始状态为绿灯
private AutoResetEvent _autoResetEvent = new AutoResetEvent(true); private static int _count = ; public AutoResetEventDemo()
{
this.InitializeComponent();
} protected override void OnNavigatedTo(NavigationEventArgs e)
{
ManualResetEvent sleep = new ManualResetEvent(false); Task tas = Task.Run(
() =>
{
while (true)
{
// WaitOne() - 判断:绿灯则进入,红灯则阻塞,进入之后自动 Reset()
_autoResetEvent.WaitOne(); /*
* WaitOne(1000)
* 1、如果当前是绿灯则进入,进入之后自动 Reset()
* 2、如果当前是红灯则阻塞
* a) 1000 毫秒之内收到 Set() 信号则进入,进入之后自动 Reset()
* b) 1000 毫秒之后如果还没收到 Set() 信号则强行进入,进入之后自动 Reset()
*/ IAsyncAction ignored = Windows.System.Threading.ThreadPool.RunAsync(
(threadPoolWorkItem) =>
{
// 在当前线程 sleep 1000 毫秒(WinRT 中没有 Thread.Sleep() 了)
sleep.WaitOne(); OutMsg(string.Format("count:{0}, time:{1}", ++_count, DateTime.Now.ToString("mm:ss"))); // Set() - 发出绿灯信号,并设置为绿灯
_autoResetEvent.Set(); },
WorkItemPriority.High);
}
});
} private void OutMsg(string msg)
{
var ignored = Dispatcher.RunAsync(
Windows.UI.Core.CoreDispatcherPriority.High,
() =>
{
lblMsg.Text = msg;
});
}
}
}

OK
[源码下载]

重新想象 Windows 8 Store Apps (47) - 多线程之线程同步: Semaphore, CountdownEvent, Barrier, ManualResetEvent, AutoResetEvent的更多相关文章

  1. 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLock

    [源码下载] 重新想象 Windows 8 Store Apps (46) - 多线程之线程同步: Lock, Monitor, Interlocked, Mutex, ReaderWriterLoc ...

  2. 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法

    [源码下载] 重新想象 Windows 8 Store Apps (42) - 多线程之线程池: 延迟执行, 周期执行, 在线程池中找一个线程去执行指定的方法 作者:webabcd 介绍重新想象 Wi ...

  3. 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel)

    [源码下载] 重新想象 Windows 8 Store Apps (43) - 多线程之任务: Task 基础, 多任务并行执行, 并行运算(Parallel) 作者:webabcd 介绍重新想象 W ...

  4. 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换

    [源码下载] 重新想象 Windows 8 Store Apps (44) - 多线程之异步编程: 经典和最新的异步编程模型, IAsyncInfo 与 Task 相互转换 作者:webabcd 介绍 ...

  5. 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithProgress, IAsyncOperationWithProgress

    [源码下载] 重新想象 Windows 8 Store Apps (45) - 多线程之异步编程: IAsyncAction, IAsyncOperation, IAsyncActionWithPro ...

  6. 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationContext, CoreDispatcher, ThreadLocal, ThreadStaticAttribute

    [源码下载] 重新想象 Windows 8 Store Apps (48) - 多线程之其他辅助类: SpinWait, SpinLock, Volatile, SynchronizationCont ...

  7. 重新想象 Windows 8 Store Apps 系列文章索引

    [源码下载][重新想象 Windows 8.1 Store Apps 系列文章] 重新想象 Windows 8 Store Apps 系列文章索引 作者:webabcd 1.重新想象 Windows ...

  8. 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo

    [源码下载] 重新想象 Windows 8 Store Apps (34) - 通知: Toast Demo, Tile Demo, Badge Demo 作者:webabcd 介绍重新想象 Wind ...

  9. 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解

    [源码下载] 重新想象 Windows 8 Store Apps (35) - 通知: Toast 详解 作者:webabcd 介绍重新想象 Windows 8 Store Apps 之 通知 Toa ...

随机推荐

  1. LNAMP架构中后端Apache获取用户真实IP地址的2种方法(转)

    一.Nginx反向代理配置: 1.虚拟主机配置 复制代码代码如下: location / {    try_files $uri @apache;} location @apache {interna ...

  2. linux epoll 开发指南-【ffrpc源码解析】

    摘要 关于epoll的问题很早就像写文章讲讲自己的看法,但是由于ffrpc一直没有完工,所以也就拖下来了.Epoll主要在服务器编程中使用,本文主要探讨服务器程序中epoll的使用技巧.Epoll一般 ...

  3. Cocos2d-JS项目之四:UI界面的优化

    测试环境: iphone4.iOS6.1.2.chrome 37.2062.60,Cocos2d-js 3.6 之前写了不少,实际项目也按这个去优化了,也有效果,但到最后才发现,尼玛,之前都搞错了,之 ...

  4. python string.py 源码分析 三:maketrans

    l = map(chr, xrange(256)) #将ascii转为字符串 _idmap = str('').join(l) del l # Construct a translation stri ...

  5. Python Flask UnicodeDecodeError 编码错误解决

    折腾Python做快速Web开发.最后定下来用Flask,相对教程全面. utf8编码上遇到问题,所有文件已经是utf8编码保存,加载css.js等静态文件,如果用GBK编码就正常:用utf8就报Un ...

  6. dlib库使用

    最近的工作中用到了dlib这个库,该库是一个机器学习的开源库,使用起来很方便,直接包含头文件即可,并且不依赖于其他库(自带图像编解码库源码).不过由于是开源的,所以bug多少有一些,我在example ...

  7. 科谱,如何单机环境下合理的备份mssql2008数据库

    前言: 终于盼来了公司的自用服务器:1U.至强CPU 1.8G 4核.16G内存.500G硬盘 X 2 (RAID1);装了64位win2008,和64位mssql2008.仔细把玩了一天把新老业务系 ...

  8. Go语言TCP/UDP Socket编程

    1. TCP编程 TCPClient // TCPClient project main.go package main import ( "fmt" "net" ...

  9. netty 编/解码处理

    1.LineBasedFrameDecoder 1.先找到结束符索引 private static int findEndOfLine(final ByteBuf buffer) { final in ...

  10. codeforces C. Diverse Permutation(构造)

    题意:1...n 的全排列中 p1, p2, p3....pn中,找到至少有k个 |p1-p2| , |p2-p3|, ...|pn-1 - pn| 互不相同的元素! 思路: 保证相邻的两个数的差值的 ...