我的程序存在问题。有一个后台工作人员按下按钮开始,在这个工作者内部是一个包含一些语音识别代码的do循环,监视用户输入并显示它。该错误如下。如果您在停止/启动按钮上取消工作人员,语音识别引擎仍在等待另外一个输入,如果您在发言之前单击开始按钮以清除它,它现在将输出2个重复结果而不是一个。
语音识别代码的很大一部分是黑客斜线复制粘贴在一起工作,所以我不是非常熟悉它。
程序代码:http://pastebin.com/tBXKs5DT
感谢任何帮助
由于
答案 0 :(得分:1)
出现问题是因为在循环到达取消检查之前松开了取消引用。为了解释这一点,我将采取一小部分代码:
_worker.DoWork += new DoWorkEventHandler((state, args) => {
do {
if (_worker.CancellationPending) {
break;
}
//recognize spoken command
} while (true);
});
当您点击停止按钮时,标记_worker
以取消。但是循环很可能等着你说出来。只有在您说完后,循环才会继续并检查取消标记。
但是:当您按开始时,_worker
引用将被覆盖并重复使用。那时你有两个循环运行。两者都看着同样的取消标志,它被设置回false。因此,如果您再说出来,它们都将处理您的语音命令,看到它们不必取消并继续。
要解决此问题,您的停止按钮应通过调用停止事件中_worker
的{{3}}来中断工作线程(button2_click)。然后在do work代码中,您需要对.Interrupt进行try / catch。如果触发异常,则检查取消标志是否为真,如果是,则断开while循环。
一些额外的附注:
File.Exists
已经返回了一个bool。在if语句中没有必要将它与true进行比较修改强> 中断的一个例子(免责声明:我手头没有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);
});