取消后后台工作器中包含的c#语音识别仍在运行

本文关键字:语音识别 运行 包含 后台 工作 取消后 | 更新日期: 2023-09-27 17:49:21

我的程序有问题。有一个后台worker,在按钮按下时开始,在这个worker中是一个do循环,其中包含一些语音识别代码,用于监视用户输入并显示它。bug如下所示。如果你取消停止/开始按钮上的工作,语音识别引擎仍然在等待一个更多的输入,如果你在说话之前点击开始按钮来清除它,它现在将输出2个重复的结果,而不是一个。

语音识别代码的很大一部分是通过复制粘贴在一起才能工作的,所以我对它不是很熟悉。

程序代码:http://pastebin.com/tBXKs5DT

感谢您的帮助

谢谢

取消后后台工作器中包含的c#语音识别仍在运行

出现问题是因为在循环到达取消检查之前丢失了取消引用。为了解释这一点,我将举一小段代码为例:

_worker.DoWork += new DoWorkEventHandler((state, args) => {
   do {
        if (_worker.CancellationPending) {
           break;
        }
        //recognize spoken command
    } while (true);
});

当你按下停止按钮时,你标志着_worker取消。但这个循环很可能正等着你大声说出来。只有在你说话之后,循环才会继续并检查取消标志。

然而:当您按下start时,_worker引用被覆盖并重用。这时有两个循环在运行。两者都查看相同的取消标志,该标志被设置回false。因此,如果你大声说话,两者都会处理你的语音命令,确保它们不必取消并继续。

要解决这个问题,你的停止按钮应该通过在停止事件(button2_click)中调用_worker上的. interrupt来中断工作线程。然后在do work代码中,您需要对中断异常进行try/catch。如果触发了异常,则检查cancel标志是否为真,如果为真,则跳出while循环。

一些额外的注释:

  • 有一个更简单的方法来听语音命令使用RecognizeAsync。看看msdn
  • 上的这个例子
  • File.Exists已经返回bool值。在if语句
  • 中没有必要将其与true进行比较。
  • 当编写更多的"hello world"程序时,尝试给每个东西一个合适的名称。代码变得相当寻宝,如名称"button1"
编辑:

一个中断的例子(免责声明:我手头没有VS,所以可能包括拼写错误)

设置取消标志和中断线程非常简单。假设你的线程(或后台工作线程,基本上是一个线程)被称为_worker,它看起来有点像这样:

_worker.CancelAsync();
_worker.Interrupt(); 

这将触发dowork事件中的中断异常。确保处理了这些异常。在您的例子中,它看起来像这样:

_worker.DoWork += new DoWorkEventHandler((state, args) => {
   do {
        try {
             if (_worker.CancellationPending) {
                 break;
             }
             //recognize spoken command
         } catch (ThreadInterruptedException) {
               if (_worker.CancellationPending) {
                 break;
               }
               //reaching this would be a odd situation. It means you interrupted your thread without canceling it. 
               //In your case this shouldn't happen, but there are cases in which you would want to support this
         }
    } while (true);
});