• 牛刀小试:使用Reactive Extensions(Rx),一行代码实现多线程任务执行规定时间后自动停止


    内容摘要:

    这是之前有一个朋友项目中实际遇到的问题:在一个窗口中,希望点击某个按钮后(或者同类操作),播放一个警告的声音,很显然,这个音频播放是用异步来实现。但又希望播放一段时间后,自动地停止播放。

    这个问题要说难也不是很难,我们无非是要想办法做一个计时,到达规定时候(例如5秒)后,强制地将线程结束掉。问题出在如何写较为理想些。

    问题分析:

    播放音频本身不难,而且在WPF中,音频播放默认就是异步的,根本不需要我们单独去启动线程。代码大致如下

                    var player = new SoundPlayer();
                    player.SoundLocation = "bell.wav";
                    player.PlayLooping();

    这里的player一般会有两个方法:Play 和PlayLooping。前者是播放一次,后者是一直播放。但他们都是异步执行的。

    如果需要同步执行,则倒是需要调用PlaySync,考虑到播放音频可能需要的时间较长,一般是不建议用同步的方式的。

    而player本身有一个Stop方法,可以终止播放(同时也会将线程关闭或者归还到线程池)。

    所以,问题的关键就在于,如何在规定的时间后,调用player.Stop方法。

    常规做法:

    从最简单粗暴的角度出发,我们可以用一个定时器,定时一定时间(例如5秒钟),到了这个时间,就调用player.Stop方法,并且将定时器也停止掉。(所以其实这个定时器只会被触发一次,我们用它的目的只是希望它能在5秒钟后被唤醒起来做事情)

                var player = new SoundPlayer();
                player.SoundLocation = "bell.wav";
    
                var timer = new DispatcherTimer(TimeSpan.FromSeconds(5), DispatcherPriority.Normal, (source, args) =>
                {
                    player.Stop();
                    ((DispatcherTimer)source).Stop();
    
                }, this.Dispatcher);
    
                timer.Start();
                player.PlayLooping();

    看起来怎么样呢?问题肯定是解决了。但是有没有更好的方法呢?

    引入Reactive Extensions:

    我联想到之前我正好在研究Reactive Extensions(简称Rx),这是微软提供的一个针对异步和事件处理的增强框架。它的官方地址在:http://msdn.microsoft.com/en-us/data/gg577609.aspx ,目前最新的版本是2.0.

    Reactive Extensions提供了一种全新的视角,让我们来处理事件,和异步任务。它首先是对异步处理和事件进行了一些包装,然后,它的核心是,通过Obserable和Observer的机制,实现所谓响应式的编程体验。最后,它结合Linq,提供了语法上面的极大便利。

    我对Reactive Extensions的研究也还算不上透彻,逐渐会有一些更多的分享出来吧。这个问题正好遇到了,所以想到可能用Rx来做,代码会更加易于阅读,本质上肯定也是有一个等待的过程,但不用Timer去做了。

    你可以直接在Visual Studio中导入几个Rx的Package

    image

    解决方案:

    我最终的解决方案如下。你觉得怎么样?是否有更加好的做法呢?

                Observable.Start<SoundPlayer>(() =>
                {
                    var player = new SoundPlayer();
                    player.SoundLocation = "bell.wav";
                    player.PlayLooping();
    
                    return player;
                }).Delay(TimeSpan.FromSeconds(5)).Subscribe(player => player.Stop());
     
     
    【备注】本来想要做一个视频的,但因为近日都在外讲课,嗓子要尽量保护。所以就通过文字写出来吧
    完整代码请通过这里下载 https://files.cnblogs.com/chenxizhang/WpfApplicationSample-rx.zip
     
  • 相关阅读:
    使用asp.net core 3.0 搭建智能小车1
    Exceptionless—本地部署
    SQLserver2016对字段是json对象查询
    Hello,World!
    计算机网络(一)
    《Unity Shader入门精要》读书笔记(抄1)
    模仿不知道哪个版本的AppleWatch界面UI(wpf)
    仿制shazzam的简单功能,将hlsl转换为WPF中的ShaderEffect
    CAST()函数可以进行数据类型的转换。
    ORA-00984: 列在此处不允许 SQL parse error location
  • 原文地址:https://www.cnblogs.com/chenxizhang/p/2694062.html
Copyright © 2020-2023  润新知