We have our thesis revision and one panelist said that to make our speech recognition system better is to add a way to process a command.
For example if i give a default command
case "What time is it?":
WVASRS.Speak("time");
break;
I want the system to be able to tell the user that the COMMAND is still processing before the user can give another command. Something like:
//I will give a command while the the other command is processing
case "What day is it":
WVASRS.Speak("day");
break;
WVASRS.Speak("Another command is still processing. Please Wait for a few seconds before you can give another command.");
Well, if found something on MSDN but it just does nothing. here is the snippet:
// Assign input to the recognizer and start asynchronous
// recognition.
recognizer.SetInputToDefaultAudioDevice();
completed = false;
Console.WriteLine("Starting asynchronous recognition...");
recognizer.RecognizeAsync(RecognizeMode.Multiple);
// Wait 30 seconds, and then cancel asynchronous recognition.
Thread.Sleep(TimeSpan.FromSeconds(30));
recognizer.RecognizeAsyncCancel();
// Wait for the operation to complete.
while (!completed)
{
Thread.Sleep(333);
}
Console.WriteLine("Done.");
The code from MSDN is more or less correct, you just miss the handler of recognized command, see the complete example here:
recognizer.SpeechRecognized +=
new EventHandler<SpeechRecognizedEventArgs>(recognizer_SpeechRecognized);
and later
// Handle the SpeechRecognized event.
static void recognizer_SpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (actionRunning) {
speak("Busy");
}
if (e.Result.Text.Equals("what is the time")) {
actionRunning = true;
startAction()
}
Console.WriteLine("Speech recognized: " + e.Result.Text);
}
Related
i wanna know the current system state whether its suspend or resume. i already tried SystemEvents.PowerModeChanged += SystemEvents_PowerModeChanged;
private void SystemEvents_PowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
log.DebugFormat("System Power event {0}", e.Mode.ToString());
}
i wanna fetch the status of a system on frequent interval. i dont wanna use WMI query also. is there any other way to detect the system state.
Then, you can use SystemEvents.PowerModeChanged event to know whether the system is getting suspended (When you hibernate or sleep the suspend will happen).
SystemEvents.PowerModeChanged += new PowerModeChangedEventHandler(OnPowerModeChanged);
private static void OnPowerModeChanged(object sender, PowerModeChangedEventArgs e)
{
switch (e.Mode)
{
case PowerModes.Resume:
MessageBox.Show("PowerMode: OS is resuming from suspended state");
break;
case PowerModes.Suspend:
MessageBox.Show("PowerMode: OS is about to be suspended");
break;
}
}
Hope this helps.
My program works like this:
I press a radio button which opens the port.
Next i press a button "Read" which starts a thread that reads data continously from the Serial Port using port.ReadLine() and prints it in a textbox;
I have another radio which should first join the thread and after that close the port;the problem is the printing goes well until i close the port when the UI freezes.
public Form1()
{
mythread = new Thread(ReadFct);
myPort = new SerialPort("COM3", 9600);
myPort.ReadTimeout = 3500;
InitializeComponent();
foreach (var t in Constants.ComboParameters)
this.paramCombo.Items.Add(t);
radioClose.CheckedChanged += new EventHandler(radioButtonCheckedChanged);
radioOpen.CheckedChanged += new EventHandler(radioButtonCheckedChanged);
}
Below is the function attached to the thread
void ReadFct()
{
string aux = "";
while (readCondition)
{
if (myPort.IsOpen)
aux = myPort.ReadLine();
this.SetText(aux);
}
}
Below is the radio button event handler
public void radioButtonCheckedChanged(object sender,EventArgs e)
{
if (radioOpen.Checked && !myPort.IsOpen)
try
{
myPort.Open();
mythread.Start();
}
catch (Exception)
{
MessageBox.Show("Nu s-a putut deschide port-ul");
}
if (radioClose.Checked && myPort.IsOpen)
{
readCondition = false;
mythread.Join();
myPort.Close();
// myPort.DataReceived -= DataReceivedHandler;
}
}
The read button function:
private void readbtn_Click(object sender, EventArgs e)
{
if (!myPort.IsOpen)
MessageBox.Show("PORT NOT OPENED!");
else
{
// myPort.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
readCondition = true;
if (!mythread.IsAlive)
{
mythread = new Thread(ReadFct);
mythread.Start();
}
}
I have used what MSDN suggest when changing control from another thread:
private void SetText(string text)
{
if (this.textBox1.InvokeRequired)
{
StringTb del = new StringTb(SetText);
this.Invoke(del, new object[] { text });
}
else
SetData = text;
}
It's hard to know exactly what you need, lacking a good Minimal, Complete, and Verifiable code example to illustrate the question. That said, the issue here is that the Thread.Join() method causes that thread to stop doing any other work, and the thread you use to call that method is the thread that handles all of the user interface. Worse, if your port never receives another newline, the thread you're waiting on will never terminate, because you're stuck waiting on the ReadLine() method. Even worse, even if you do get a newline, if that happens while you're stuck waiting on the Thread.Join(), the call to Invoke() will deadlock, because it needs the UI thread to do its work, and the Thread.Join() call is preventing it from getting the UI thread.
In other words, your code has multiple problems, any one of which could cause problems, but all of which together mean it just can't possibly work.
There are a variety of strategies to fix this, but IMHO the best is to use await. The first step in doing that is to change your I/O handling so that it's done asynchronously instead of dedicating a thread to it:
// Ideally, you should rename this method to "ReadFctAsync". I am leaving
// all names intact for the same of the example though.
async Task ReadFct()
{
string aux = "";
using (StreamReader reader = new StreamReader(myPort.BaseStream))
{
while (true)
{
aux = await reader.ReadLineAsync();
// This will automatically work, because the "await" will automatically
// resume the method execution in the UI thread where you need it.
this.SetText(aux);
}
}
}
Then, instead of creating a thread explicitly, just create a Task object by calling the above:
public Form1()
{
// In this approach, you can get rid of the "mythread" field altogether
myPort = new SerialPort("COM3", 9600);
myPort.ReadTimeout = 3500;
InitializeComponent();
foreach (var t in Constants.ComboParameters)
this.paramCombo.Items.Add(t);
radioClose.CheckedChanged += new EventHandler(radioButtonCheckedChanged);
radioOpen.CheckedChanged += new EventHandler(radioButtonCheckedChanged);
}
public async void radioButtonCheckedChanged(object sender,EventArgs e)
{
if (radioOpen.Checked && !myPort.IsOpen)
{
try
{
myPort.Open();
await ReadFct();
// Execution of this method will resume after the ReadFct() task
// has completed. Which it will do only on throwing an exception.
// This code doesn't have any continuation after the "await", except
// to handle that exception.
}
catch (Exception)
{
// This block will catch the exception thrown when the port is
// closed. NOTE: you should not catch "Exception". Figure out what
// *specific* exceptions you expect to happen and which you can
// handle gracefully. Any other exception can mean big trouble,
// and doing anything other than logging and terminating the process
// can lead to data corruption or other undesirable behavior from
// the program.
MessageBox.Show("Nu s-a putut deschide port-ul");
}
// Return here. We don't want the rest of the code executing after the
// continuation, because the radio button state might have changed
// by then, and we really only want this call to do work for the button
// that was selected when the method was first called. Note that it
// is probably even better if you just break this into two different
// event handlers, one for each button that might be checked.
return;
}
if (radioClose.Checked && myPort.IsOpen)
{
// Closing the port should cause `ReadLineAsync()` to throw an
// exception, which will terminate the read loop and the ReadFct()
// task
myPort.Close();
}
}
In the above, I have completely ignored the readbtn_Click() method. Lacking a good MCVE, it's not clear what role that button plays in the overall scheme. You seem to have a radio button group (of two buttons) that control whether the port is open or closed. It is not clear why then you have an additional regular button that is seemingly able to also open the port and start reading, independently of the radio group.
If you want that extra button, it seems to me that all it ought to do is change the radio group state, by checking the "open" radio button. Then let the radio group buttons handle the port state and reading. If you need more specific advice as to how to fully integrate my code example above with your entire UI, you will need to provide more detail, preferably in a new question. That new question must include a good MCVE.
First off I must admit that I'm fairly new to C#. I am using C# speech recognition for writing an application that will interface between a human and a robot. An example of a dialogue is as follows:
Human: Ok Robot, Drill.
Robot: Where?
Human shows where.
Robot: I am ready to drill.
Human: Ok Robot, start.
My approach is having two speech recognizes. The first one is for higher level commands such as "Drill", "Cut Square", "Cut Rectangle", "Play Game" etc. The second one is for start/stop commands for each of the higher level tasks.
This is my current code:
using System.IO;
using System.Speech.Recognition;
using System.Speech.Synthesis;
namespace SpeechTest
{
class RobotSpeech
{
public SpeechRecognitionEngine MainRec = new SpeechRecognitionEngine();
public SpeechRecognitionEngine SideRec = new SpeechRecognitionEngine();
public SpeechSynthesizer Synth = new SpeechSynthesizer();
private Grammar mainGrammar;
private Grammar sideGrammar;
private const string MainCorpusFile = #"../../../MainRobotCommands.txt";
private const string SideCorpusFile = #"../../../SideRobotCommands.txt";
public RobotSpeech()
{
Synth.SelectVoice("Microsoft Server Speech Text to Speech Voice (en-US, ZiraPro)");
MainRec.SetInputToDefaultAudioDevice();
SideRec.SetInputToDefaultAudioDevice();
BuildGrammar('M');
BuildGrammar('S');
}
private void BuildGrammar(char w)
{
var gBuilder = new GrammarBuilder("Ok Robot");
switch (w)
{
case 'M':
gBuilder.Append(new Choices(File.ReadAllLines(MainCorpusFile)));
mainGrammar = new Grammar(gBuilder) { Name = "Main Robot Speech Recognizer" };
break;
case 'S':
gBuilder.Append(new Choices(File.ReadAllLines(SideCorpusFile)));
sideGrammar = new Grammar(gBuilder) { Name = "Side Robot Speech Recognizer" };
break;
}
}
public void Say(string msg)
{
Synth.Speak(msg);
}
public void MainSpeechOn()
{
Say("Speech recognition enabled");
MainRec.LoadGrammarAsync(mainGrammar);
MainRec.RecognizeAsync(RecognizeMode.Multiple);
}
public void SideSpeechOn()
{
SideRec.LoadGrammarAsync(sideGrammar);
SideRec.RecognizeAsync();
}
public void MainSpeechOff()
{
Say("Speech recognition disabled");
MainRec.UnloadAllGrammars();
MainRec.RecognizeAsyncStop();
}
public void SideSpeechOff()
{
SideRec.UnloadAllGrammars();
SideRec.RecognizeAsyncStop();
}
}
}
In my main program I have the speech recognized event as follows:
private RobotSpeech voiceIntr;
voiceIntr.MainRec.SpeechRecognized += MainSpeechRecognized;
private void MainSpeechRecognized(object sender, SpeechRecognizedEventArgs e)
{
if (!e.Result.Text.Contains("Ok Bishop")) return;
switch (e.Result.Text.Substring(10))
{
case "Go Home":
voiceIntr.Say("Going to home position.");
UR10MoveRobot.GoHome();
break;
case "Say Hello":
voiceIntr.Say("Hello. My name is Bishop.");
break;
case "Drill":
voiceIntr.Say("Show me where you want me to drill.");
// Actual code will be for observating the gestured pts and
// returning the number of pts observed
var msg = "I am ready to drill those " + new Random().Next(2, 5) + " holes.";
voiceIntr.Say(msg);
voiceIntr.SideSpeechOn();
voiceIntr.SideSpeechOff();
break;
case "Cut Outlet":
voiceIntr.Say("Show me where you want me to cut the outlet.");
// Launch gesture recognition to get point for cutting outlet
break;
case "Stop Program":
voiceIntr.Say("Exiting Application");
Thread.Sleep(2200);
Application.Exit();
break;
}
}
The problem I am having is, when one of the MainRec events gets triggered, I am in one the cases here. Now I only want to listen for "Ok Robot Start" and nothing else which is given by the SideRec. If I subscribe to that event here this will go to another eventhandler with a switch case there from which I wouldn't know how to get back to the main thread.
Also after telling the human that the robot is ready for drilling, I would like it to block until it receives an answer from the user for which I need to use a synchronous speech recognizer. However, after a particular task I want to switch off the recognizer which I can't do if its synchronous.
Here are the files for the grammers:
MainRobotCommands.txt
Go Home
Say Hello
Stop Program
Drill
Start Drilling
Cut Outlet
Cut Shap
Play Tic-Tac-Toe
Ready To Play
You First
SideRobotCommands.txt:
Start
Stop
The speech recognition is only a part of a bigger application hence it has to be async unless I want to make it preciously block. I am sure there is better way to design this code, but I'm not sure my knowledge of C# is enough for that. Any help is greatly appreciated!
Thanks.
My approach is having two speech recognizes.
There is no need for 2 recognizers, you can have just 1 recognizer and load/unload grammars when you need them.
private void BuildGrammar(char w)
This is not a straightforward programming style to use switch statement and invoke same function two times with different arguments. Just create two grammars sequentially.
The problem I am having is, when one of the MainRec events gets triggered, I am in one the cases here. Now I only want to listen for "Ok Robot Start" and nothing else which is given by the SideRec. If I subscribe to that event here this will go to another eventhandler with a switch case there from which I wouldn't know how to get back to the main thread.
If you have one recognizer it's enough to have a single handler and do all work there.
Also after telling the human that the robot is ready for drilling, I would like it to block until it receives an answer from the user for which I need to use a synchronous speech recognizer. However, after a particular task I want to switch off the recognizer which I can't do if its synchronous.
It not easy to mix async and sync style in the same design. You need to use either sync programming or async programming. For event-based software there is actually no need to mix, you can work in strictly async paradigm without waiting. Just start new drilling action inside MainSpeechRecognized event handler when "ok drill" is recognized. You can also synthesize audio in async mode without waiting for the result and continue processing in on SayCompleted handler.
To track the state of your software you can create a state variable and check it in event handlers to understand in what state you are and choose next action.
This programming paradigm is called "Event-driven programming", you can read a lot about it in network, check Wikipedia page and start with this tutorial.
I'm currently making a program to simulate a set of ATMs in visual C#. It's supposed to stop somebody accessing their account if it has already been accessed from a different location. Is it possible to show a message that the account has already been accessed while a semaphore is waiting?
Here is the part of the code where the semaphore is used:
private void button1_Click(object sender, EventArgs e)
{
count++;
if (count == 1)
{
account = findAccount();
if (findAccount() != 5)
{
textBox1.Text = "Please Enter Your Pin";
}
else
{
textBox1.Text = "Please Enter Your Account Number";
count = 0;
}
textBox2.Clear();
}
if (count == 2)
{
if (findPin(account) == true)
{
semaphore.WaitOne();
textBox1.Text = "1: Take Out Cash \r\n2: Balance \r\n3: Exit";
}
else
{
semaphore.Release();
textBox1.Text = "Please Enter Your Account Number";
count = 0;
}
textBox2.Clear();
}
if (count == 3)
{
atm();
}
if (count == 4)
{
withdraw();
}
if (count == 5)
{
int value = Convert.ToInt32(textBox2.Text);
customWithdrawl(value);
}
}
Consider doing two calls to WaitOne. The first call will have a timeout of zero and return a bool that will tell you whether or not you got the semaphore, or someone else still owns it. Two things can happen from there:
1) If someone else owns it, pop up a message that says "Someone else owns the semaphore" and call WaitOne again, but without a timeout (like you're doing now). After the 2nd call to WaitOne returns, close the window that you popped up a second ago..
2) If your call to waitOne with 0 timeout returns true, then you got the semaphore on the 1st try. No need to pop up a window.
Example:
if( semaphore.WaitOne(0) ) //This returns immediately
{
//We own the semaphore now.
DoWhateverYouNeedToDo();
}
else
{
//Looks like someone else already owns the semaphore.
PopUpNotification();
semaphore.WaitOne(); //This one will block until the semaphore is available
DoWhateverYouNeedToDo();
CloseNotification();
}
semaphore.Release();
Note, there are some other issues lurking here.
You probably want to use a try/finally block to release the semaphore to ensure that it gets released across all exception paths.
It's also probably a bad idea to call semaphore.WaitOne() from the GUI thread because the application will become non-responsive while it waits. In fact, you may not see the result of PopUpNotification() if you've hung the GUI thread while doing the 2nd Wait. Consider doing the long wait on a 2nd thread and raising an event back on the GUI thread once you own the semaphore
Consider the following design to resolve Issue 2:
private void button1_Click(object sender, EventArgs e)
{
if(AcquireSemaphoreAndGenerateCallback())
{
//Semaphore was acquired right away. Go ahead and do whatever we need to do
DoWhateverYouNeedToDo();
semaphore.Release()
}
else
{
//Semaphore was not acquired right away. Callback will occur in a bit
//Because we're not blocking the GUI thread, this text will appear right away
textBox1.Text = "Waiting on the Semaphore!";
//Notice that the method returns right here, so the GUI will be able to redraw itself
}
}
//This method will either acquire the semaphore right away and return true, or
//have a worker thread wait on the semaphore and return false. In the 2nd case,
//"CallbackMethod" will run on the GUI thread once the semaphore has been acquired
private void AcquireSemaphoreAndGenerateCallback()
{
if( semaphore.WaitOne(0) ) //This returns immediately
{
return true; //We have the semaphore and didn't have to wait!
}
else
{
ThreadPool.QueueUserWorkItem(new WaitCallback(Waiter));
return false; //Indicate that we didn't acquire right away
}
}
//Wait on the semaphore and invoke "CallbackMethod" once we own it. This method
//is meant to run on a background thread.
private void Waiter(object unused)
{
//This is running on a separate thread
Semaphore.WaitOne(); //Could take a while
//Because we're running on a separate thread, we need to use "BeginInvoke" so
//that the method we're calling runs on the GUI thread
this.BeginInvoke(new Action(CallbackMethod));
}
private void CallbackMethod()
{
textBox1.Text = string.Empty; //Get rid of the "Waiting For Semaphore" text. Can't do this if we're not running on the GUI thread
DoWhateverYouNeedToDo();
semaphore.Release();
}
Now, this solution could also be fraught with peril. It's kind of hard to follow the execution of the program because it jumps around from method to method. If you have an exception, it could be difficult to recover from and make sure all of your program state is correct. You also have to keep track of things like the account number and the pin numbers through all of these method calls. In order to do that, Waiter and CallbackMethod should probably take some parameter that tracks this state that gets passed along to each step. There's also no way to abort waiting (a time out). It will probably work, but shouldn't make it into any production code because it would be too difficult to maintain or extend.
If you really wanted to do it right, you should consider encapsulating the ATM logic in an object that will raise events that the GUI can subscribe to. You could have a method like ATM.LogInAsync(Account,Pin) that you could call. This method would return immediately, but some time later, an event on the ATM class like "LogInComplete" would fire. This event would have a custom EventArgs object that would contain data to trace which log-in has occurred (mainly the Account number). This is called the Event-based Asynchronous Pattern
Alternatively, if you're using C# 5.0, you can use the new Async/Await syntax in the AcquireSemaphoreAndGenerateCallback() method. That's probably the easiest way because the compiler will handle most of the complexities for you
Yes, you may show your message/form/messagebox right before the Wait method. Then when it receives the signal to unblock, you hide your message.
When I use this task I can't do any thing in my application after saving the contact except showing a messagebox with a message how can I return again to my application when this task completed !!
This should work out the box. When task is finished your application takes control again. You can control task result using Completed event handler
this.saveContactTask.Completed += new EventHandler<SaveContactResult>(saveContactTask_Completed);
private void saveContactTask_Completed(object sender, SaveContactResult e)
{
switch (e.TaskResult)
{
case TaskResult.OK:
MessageBox.Show("Contact is successfully saved.");
break;
case TaskResult.Cancel:
MessageBox.Show("The user canceled the task.");
break;
case TaskResult.None:
MessageBox.Show("NO information regarding the task result is available.");
break;
}
}
Here you can find fully functional example which works exactly as you want. You may take a look and compare with your implementation
http://windowsphonegeek.com/tips/8-How-to-use-SaveContactTask-in-Windows-Phone-Mango