前言
因为需要一个自动播放和暂停图片的功能,所以就非常自然想到了创建一个线程,用点击事件控制线程的暂停和启动。
一、暂停与恢复
线程的启动和恢复完成此功能的核心知识,现在实现线程的暂停与恢复可以通过AutoResetEvent和ManualResetEvent这两个阻塞事件类来实现。
两种事件的不同
- AutoResetEvent是自动阻塞,同时只允许一个线程通过一次,然后继续阻塞,类似于小区门口测体温
- ManualResetEvent是手动阻塞,打开后需要手动阻塞,否则会一直打开;阻塞后需要手动打开,否则会一直阻塞,类似于水龙头
Set()、Reset()与WaitOne()
- WaitOne()阻塞线程,等待信号;有带参数的重载,设置等待时间以及等待超时的操作
- Set()方法可以发出可通过信号
- Reset()方法可以发出不可通过信号
因为功能需要,所以选择使用ManualResetEvent。
二、功能实现
1.按钮事件(播放和停止)
为按钮绑定command
<!-- 播放按钮 command-->
<Button BorderThickness="0" Background="#F4F4F7" Command="{Binding PlayCommd}">
<!-- 暂停按钮 command-->
<Button BorderThickness="0" Background="#F4F4F7" Command="{Binding StopCommd}">
ViewModel
public ICommand PlayCommd { get; }
public ICommand StopCommd { get; }
2. 线程和ManualResetEvent
public ICommand PlayCommd { get; }
public ICommand StopCommd { get; }
private Thread playThread; //图片切换线程
private int current = 0; //当前循环的进度
private static ManualResetEvent mREvent = new ManualResetEvent(true); //设置true可以通过
public MainWindowViewModel() {
PlayCommd = new RelayCommand(() => {
mREvent.Set();
PlayFun();
});
StopCommd = new RelayCommand(() => {
mREvent.Reset();
});
}
private void PlayFun()
{
if (playThread == null) {
playThread = new Thread(async () => {
//pictures 为list 保存了图片的地址和序号。
for (;current<pictures.Count;current++) {
FrontImg = pictures[current].Url;
ImageTag = pictures[current].No;
int m = 300;
await Task.Delay(m); //sleep时间
mREvent.WaitOne();
}
});
playThread.Start();
}
}
播放
总结
以上就是今天要讲的内容,本文仅仅简单介绍了ManualResetEvent控制线程的暂停和恢复。实现了图片自动切换的功能。如果你有更好的方法,可以留言讨论一下,3Q