Reputation: 11
I am having a issue with my program. There is a background worker that starts on button press and inside this worker is a do loop containing some speech recognition code that monitors for user input and displays it. The bug is as followed. If you cancel the worker on stop/start button the speech recognition engine is still waiting for one more input, and if you click the start button before speaking to clear it out it will now output 2 duplicate results instead of one.
A good portion of the speech recognition code was hack slash copy pasted together to get working, so im not intimately familiar with it.
Program Code: http://pastebin.com/tBXKs5DT
any help is appreciated
Thanks
Upvotes: 0
Views: 352
Reputation: 712
The problem occurs because you loose the cancel reference before your loop reaches the the cancel check. To explain this I'll take a small sample of your code:
_worker.DoWork += new DoWorkEventHandler((state, args) => {
do {
if (_worker.CancellationPending) {
break;
}
//recognize spoken command
} while (true);
});
When you hit the stop button you flag the _worker
to cancel. But the loop is most likely waiting for you to speek up. Only after you've spoken the loop will continue and check the cancellation flag.
However: When you press start the _worker
reference is overwritten and reused. At that point you got two loops running. Both looking at the same cancellation flag which is set back to false. So if you then speak up both will process your voice command, see that they do not have to cancel and carry on.
To resolve this your stop button should interrupt the worker thread by calling the .Interrupt on the _worker
in your stop event (button2_click). Then inside the do work code you need to have a try/catch for a interrupt exception. If the exception is triggered then check if the cancel flag is true, if so then break out of the while loop.
A few extra side notes:
File.Exists
already returns a bool. There is no need to compare it to true in your if statementsEDIT: A example for the interrupt (Disclaimer: I don't have VS at hand here, so typos might be included)
Setting the cancel flag and interrupting a thread is quite simple. Assuming that your thread (or background worker which is basically a thread) is called _worker
it looks somewhat like this:
_worker.CancelAsync();
_worker.Interrupt();
This will trigger a interrupt exception inside that dowork event. Be sure that these exceptions are handled. In your case that would look something like this:
_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);
});
Upvotes: 1