设为首页 收藏本站
查看: 963|回复: 0

重新想象 Windows 8 Store Apps (47)

[复制链接]

尚未签到

发表于 2015-5-22 08:09:33 | 显示全部楼层 |阅读模式
  [源码下载]




重新想象 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










  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 tasks = new List();
// 模拟 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;
});
}
}
}
  
2、演示 CountdownEvent 的使用
Thread/Lock/CountdownEventDemo.xaml










  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(100))
{
// AddCount(), AddCount(int signalCount) - 增加 1 个信号,或增加指定数量的信号
// Reset(), Reset(int count) - 重置为初始的信号数量,或重置为指定的信号数量
// Signal(), Signal(int signalCount) - 减少 1 个信号,或减少指定数量的信号
// CurrentCount - 获取当前的信号数量
for (int i = 0; i < 100; 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










  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, // 初始有 5 个参与者
(ctx) => // 屏障解除之后
                {
var ignored = Dispatcher.RunAsync(CoreDispatcherPriority.High,
() =>
{
lblMsg.Text = "count: " + _count.ToString();
});
});
for (int i = 0; i < 5; i++)
{
Task task = Task.Run(
() =>
{
Interlocked.Increment(ref _count);
// 某一个参与者已经到达屏障了
                        barrier.SignalAndWait();
// SignalAndWait(int millisecondsTimeout) - 指定一个超时时间
// SignalAndWait(CancellationToken cancellationToken) - 指定一个 CancellationToken
                    });
}
}
}
}
  
4、演示 ManualResetEvent 的使用
Thread/Lock/ManualResetEventDemo.xaml










  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 = 0;
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(1000);
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










  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 = 0;
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(1000);
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
[源码下载]

运维网声明 1、欢迎大家加入本站运维交流群:群②:261659950 群⑤:202807635 群⑦870801961 群⑧679858003
2、本站所有主题由该帖子作者发表,该帖子作者与运维网享有帖子相关版权
3、所有作品的著作权均归原作者享有,请您和我们一样尊重他人的著作权等合法权益。如果您对作品感到满意,请购买正版
4、禁止制作、复制、发布和传播具有反动、淫秽、色情、暴力、凶杀等内容的信息,一经发现立即删除。若您因此触犯法律,一切后果自负,我们对此不承担任何责任
5、所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其内容的准确性、可靠性、正当性、安全性、合法性等负责,亦不承担任何法律责任
6、所有作品仅供您个人学习、研究或欣赏,不得用于商业或者其他用途,否则,一切后果均由您自己承担,我们对此不承担任何法律责任
7、如涉及侵犯版权等问题,请您及时通知我们,我们将立即采取措施予以解决
8、联系人Email:admin@iyunv.com 网址:www.yunweiku.com

所有资源均系网友上传或者通过网络收集,我们仅提供一个展示、介绍、观摩学习的平台,我们不对其承担任何法律责任,如涉及侵犯版权等问题,请您及时通知我们,我们将立即处理,联系人Email:kefu@iyunv.com,QQ:1061981298 本贴地址:https://www.yunweiku.com/thread-69340-1-1.html 上篇帖子: windows 8 metro 开发学习资源链接 下篇帖子: 重新想象 Windows 8 Store Apps (46)
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

扫码加入运维网微信交流群X

扫码加入运维网微信交流群

扫描二维码加入运维网微信交流群,最新一手资源尽在官方微信交流群!快快加入我们吧...

扫描微信二维码查看详情

客服E-mail:kefu@iyunv.com 客服QQ:1061981298


QQ群⑦:运维网交流群⑦ QQ群⑧:运维网交流群⑧ k8s群:运维网kubernetes交流群


提醒:禁止发布任何违反国家法律、法规的言论与图片等内容;本站内容均来自个人观点与网络等信息,非本站认同之观点.


本站大部分资源是网友从网上搜集分享而来,其版权均归原作者及其网站所有,我们尊重他人的合法权益,如有内容侵犯您的合法权益,请及时与我们联系进行核实删除!



合作伙伴: 青云cloud

快速回复 返回顶部 返回列表