C# Speech Recognition Contained in Background Worker still running after canceled - c#

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

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:
There is a easier way to listen to voice commands using the RecognizeAsync. Have a look at this example on msdn
File.Exists already returns a bool. There is no need to compare it to true in your if statements
When writing more then a 'hello world' program try to give everything a proper name. The code becomes quite the treasure hunt with names like "button1"
EDIT:
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);
});

Related

What does messageBox.Show() do in order to stop the execution of a UI thread?

In a WPF application, I am outputting messages to a text box and in between these messages I am calling a function that sets up an instrument. However the messages all appear at the same time (at end of function call).
I do not really know how to explain my problem clearly. I'll try...
I have a WPF application which takes data from an instrument using the serial port. The application contains some buttons and a text box for output messages. Upon pressing a button, the application sends a command to the instrument to change some parameters (through a function Set_COMM_MODE()), and returns. The change takes around 5-10 seconds. Thus what I did is: I outputted a "Please Wait" message before the call and a "Done" message after the call return.
The OuputText() function in the code only calls the TextBox.AppendText() method.
My Problem: All the output text is splurted out on the text box upon the call return. I expected a Please Wait... then 5-10s later a "Done" message. But it is all appearing at the same time. However, when I put a MessageBox after the 1st message (before the function call), the message appears on the textbox output (w/o the function being called). However the problem is that I have to press OK on the MessageBox in order to continue.
Q(1): How can I have the latter happening w/o having to resort to a MessageBox
Q(2): What does a MessageBox do in order to create this behaviour?
I tried: using the Dispatch.Invoke() method to run the OutputText on another thread.
This (Pause a window like MessageBox.Show()) is a similar problem to what I have, but didn't seem to get a definitive answer, and I did not understand the solution well.
void StartTest_btn_Click(object sender, RoutedEventArgs e)
{
OutputText("Please Wwait\r\n"); //<---- This should appear at once.
MessageBox.Show("Please Wwait"); //<--without this, both messages appear at same time after 10s.
Set_COMM_MODE("02"); //<--- This takes around 5-10s
OutputText("Done\r\n"); //<--- This should appear 5-10s later
}
I expect a "Please wait" to show at once, then 5-10s later the "Done" message to show, after return of function Set_COMM_MODE().
As I wrote in my comment, you should really use the (main) UI thread for UI only.
Perform any other long-running non-UI operations on worker threads.
You might not mind the "hang" UI for 10 seconds, but users will surely be annoyed. Also, blocking the UI thread will cause Windows to think that your app is frozen, so you'll get that nice "not responding" badge and all related stuff. This not only looks awful but also can cause various side-effects.
You should really take a look around and see what .NET offers you for such kind of problems.
Look, this is your workflow:
Print a message
Start initialization
???
Initialization is complete --> print "done"
Start operation
What is this? This is an asynchronous processing. You start an action and continue asynchronously - that means, only when the action is completed.
.NET offers you a lot of tools for that, e.g. the APM (Asynchronous Programming Model). But the most neat and powerful way for implementing asynchronous processing is the TAP - Task-based Asynchronous Programming pattern, better known as async/await.
Look, your problem can be solved with a couple of lines using the TAP:
async void StartTest_btn_Click(object sender, RoutedEventArgs e)
{
OutputText("Please Wait\r\n");
// Set_COMM_MODE will be executed on a worker thread!
// The main (UI) thread won't block. It will continue.
// But the StartTest_btn_Click method itself will pause until the task is finished.
await Task.Run(() => Set_COMM_MODE("02"));
// This line will only be executed, after the Set_COMM_MODE call is completed;
// furthermore, it will be executed on the UI thread again!
OutputText("Done\r\n");
}
You should really learn more about the modern programming techniques, which the TAP is one of.

Application.Exit(): Does it start a new thread (my program continues execution in parallel)?

I have a multi-threaded application, and both in the main UI thread and in other background threads, I have stop-methods that call Application.Exit().
The weird thing is that after the call, the program continues on to the next line (and then eventually exits). The obvious problem with this can be explained with the simple code below:
if (XYZ) Application.Exit();
Globals.Instance.LoggerDictionary["ApplicationLog"].Log("Bla bla...");
And this:
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
var button = sender as Button;
if (button != null && string.Equals(button.Name, #"CloseButton"))
{
//FormClosing event raised by a user created button action
}
else
{
//FormClosing event raised by program or the X in top right corner
Globals.Instance.LoggerDictionary["ApplicationLog"].Dispose();
Globals.Instance.LoggerDictionary["OtherLog"].Dispose();
MemoryHandler.Instance.Dispose();
}
}
As seen the FormClosing method ensures that cleanup of unmanaged resources is done. So, in many cases the application moves on to the line below Application.Exit(), and, in the example above, try to write something to the Log, which has already been disposed by the FormClosing() method.
My question is therefore: Does Application.Exit() spawn a new thread where FormClosing() is run from? If not, then why does it continue on?
http://msdn.microsoft.com/en-us/library/system.windows.forms.application.exit(v=vs.110).aspx
Informs all message pumps that they must terminate, and then closes all application windows after the messages have been processed.
This method does not terminate the process. Instant termination is rarely a useful shutdown model because it is unclear what useful shutdown actions would be skipped.
If this method does not terminate the process then clearly your code must continue to run.
This is normal and the right way to shut down the app. If you want to skip certain logic, set a flag bool isShuttingDown and react to it.
No, it does not start a new thread. It also doesn't immediately kill the UI thread. The whole point of Application.Exit is to gracefully exit the application. All forms will be asked to be closed, resources will be cleaned up, all pumped through the main application loop. When the application loop next becomes idle, rather than waiting for more messages, it will instead stop pumping messages and the application will continue running after the call to Appliaction.Run that created the message loop in the first place. That thread can then go on to do whatever (usually end; unless you've added more code).
No it does not spawn a extra thread. Looking at the reference source inside the function it will call each form's FormClosing event, it then returns control to the caller. Once the caller completes and control returns to the message loop that is when the program will actually shut down.
All of this happens on the single UI thread.

Why is this sequential operation not being executed?

I am going through this tutorial on how to perform some work in the background and in this piece of code I am confused as to why the message reading the file... is not displayed before the ReadTheFile(filename) method is called.
private void btnSelect_Click(object sender, EventArgs e)
{
OpenFileDialog ofd = new OpenFileDialog();
ofd.CheckFileExists = true;
ofd.CheckPathExists = true;
if (ofd.ShowDialog() == DialogResult.OK)
{
lblResults.Text = " ... reading the file ...";
FileReader1 fr = new FileReader1();
int numLines = fr.ReadTheFile(ofd.FileName);
lblResults.Text = string.Format("We read {0} lines", numLines.ToString());
}
}
The author explains it by saying the following, but it did not really get through to me.
Worse, even though we set the label’s Text property before we call ReadTheFile, the message loop doesn’t get a chance to process that change, and update the text, before we go out to lunch in ReadTheFile.
What does this mean? Can this be explained in simpler terms?
Worse, even though we set the label’s Text property before we call ReadTheFile, the message loop doesn’t get a chance to process that change, and update the text, before we go out to lunch in ReadTheFile.
Basically you are setting the text of label. However, you then start doing a "intensive" task that could take seconds, minutes, hours. As long as you are continuing to load the file and read the number of lines, the window will not update. That's the point of doing it in a background thread. Let the main thread continue to paint the window and handle UI stuff while your background thread processes the file.
I would continue with the tutorial. Once you get to the part where you start creating and running the background worker you may end up with one of those "Aha!" moments. =)
You may also be interested in reading up on threads in general.
http://www.codeproject.com/Articles/26148/Beginners-Guide-to-Threading-in-NET-Part-1-of-n
http://www.techrepublic.com/article/a-beginners-guide-to-threading-in-c/1044970
You could read Application.DoEvents Method .
When you run a Windows Form, it creates the new form, which then waits
for events to handle. Each time the form handles an event, it
processes all the code associated with that event. All other events
wait in the queue. While your code handles the event, your application
does not respond. For example, the window does not repaint if another
window is dragged on top.
So, until your btnSelect_Click is finished, your form will not repaint.
I'd edit my answer to remark, that one'd better not use DoEvents explicitly, as it may result in rather weird programm behaviour. (based on comment by J.Skeet).
You could read Use of Application.DoEvents() at SO also for more info. There is an extract from MSDN posted in that thread:
Calling this method causes the current thread to be suspended while
all waiting window messages are processed. If a message causes an
event to be triggered, then other areas of your application code may
execute. This can cause your application to exhibit unexpected
behaviors that are difficult to debug. If you perform operations or
computations that take a long time, it is often preferable to perform
those operations on a new thread.

WPF Method to wait for DocumentCompleted Event

I know this has been asked before, but I don't think these solutions are flexible. The DocumentCompleted event should be used to determine when the load has completed, not as a method for performing work. If you need to perform several different tasks that each have to navigate several times, placing the logic in the DocumentCompleted event turns it into a messy switch/case router that is hard to read and maintain.
You need something that can actually wait during your method performing navigation so you can continue your task in the method you are already in. My first though is an actual Wait() method.
I would think something like this is close:
void WaitForLoad()
{
isLoading = true;
while (isLoading)
{
if (Application.Current == null) break;
Dispatcher.CurrentDispatcher.Invoke(DispatcherPriority.Background, (DispatcherOperationCallback)delegate(object unused) { return null; }, null);
}
}
And set Isloading to false in the DocumentCompleted event.
You should be able to just call this method after whatever action will cause a pageload. It works, it has some issues.
1) it sends the CPU usage for the app up to 35% until the page has loaded, even if nothing else is happening.
2) if the application tries to close while its running, the loop will keep running and leave the app open with no windows, hence the need for the break when the app is null.
Can this be fixed, or am I coming at this all the wrong way?
Edit: I tried implementing the ManualResetEvent solution below, but it led to several other issues that I am not sure can be resolved without creating a messier situation than the one above. Since the WebBrowser is on the UI, locking the thread stop the entire app. If the work is done on the background thread it can be locked, but then accessing the WebBrowser becomes very difficult.
In your situation, it sounds like you want a specific thread to block while waiting for the document to load. In that case, you would do something like this:
protected ManualResetEvent _resetEvent = new ManualResetEvent(false);
public void WaitingThread()
{
_resetEvent.WaitOne();
// Do stuff after the web browser completes.
}
public void LoadWebPage()
{
webBrowser.Navigate(new Uri(url));
webBrowser.DocumentCompleted = (s, e) => { _resetEvent.Set(); };
}
Basically, when the document completes, you signal the event and any threads waiting on the event unblock and continue executing.
I noticed that you use Dispatcher.CurrentDispatcher.Invoke this is good for calling your method that somehow updates UI from another thread. But from code provided, I don't see any code in other thread then UI. So
Run that code on another thread.
On the close event of your application you can make isLoading=false; And more, if the method invoked is kind of long running stuff insert
if(!isLoading)
return;
//or in some other app suitable way break an execution
EDIT:
Even better way to handle this in multithreading, then just simply relay on boolean variable, is using some Synchonization object

How can I pause a BackgroundWorker? Or something similar

I was using a BackgroundWorker to download some web sites by calling WebClient.DownloadString inside a loop. I wanted the option for the user to cancel in the middle of downloading stuff, so I called CancelAsync whenever I found that CancellationPending was on in the middle of the loop.
But now I noticed that the function DownloadString kinda freezes sometimes, so I decided to use DownloadStringAsync instead (all this inside the other thread created with BackgroundWorker). And since I don't want to rewrite my whole code by having to exit the loop and the function after calling DownloadStringAsync, I made a while loop right after calling it that does nothing but check for a variable bool Stop that I turn true either when the DownloadStringCompleted event handler is called or when the user request to cancel the operation.
Now, the weird thing is that it works fine on the debug version; but on the release one, the program freezes in the while loop like if it were the main thread.
Sounds to me you are busy-waiting with a while loop. You should use event signaling instead, eg. a WaitHandle. A busy-waiting loop in release mode might very well consume all your cpu, giving a feeling of a freeze.
Signal the WaitHandle in DownloadStringCompleted or if the user cancels the download.
Check the MSDN docs on the WaitHandle class. There's also an example there.
Send your while loop that is checking for the cancelation to sleep for a short while (some ms). This well free up the CPU runtime for other threads and processes.
nice topic, i used
In my background worker process a double while
int icounter = 1;
while (icounter < SomeListInventory.Count)
{
while (pauseWorker == false)
{
//-----------------------
//DO SOME WORK
icounter++;
//-----------------------
}
}
And i have a button pause, that when i press it, pauseWorker (Global variable or property) becomes true and loops in the first while only, without increasing the icounter, and when i make the pauseworker=false again the process continues

Categories