Home | Contact Us | FAQ | Search & Site Map | Link to Us
Sign In | Join | Other 45 Sites in Network
HomeAnnouncementsFree MagazinesWhite PapersSubmit Content
Discussion GroupsASP.NETWindows FormsLanguages.NET FrameworkVisual Studio.NET
Articles.NET FrameworkASP.NETToolsWindows Forms
.NET DirectoryOpen Source ProjectsUser GroupsWeb Resources
Related Topics
Visual Basic 6SQL ServerMS AccessOther DB ProductsMS Server ProductsMore Topics ...

.NET Forum / Languages / Managed C++ / October 2007

Tip: Looking for answers? Try searching our database.

Can't enable a Timer in a Speech Recognized handler

Thread view: 
Enable EMail Alerts  Start New Thread
Thread rating: 
Peter Oliphant - 09 Oct 2007 00:32 GMT
Note that although this involves SAPI, it is more a question about Timers
and event handlers.

I wrote a Speech Recognize handler (SAPI), and put some code in it to enable
a Timer. It would not do it. If I bring this same code outside this event
handler, it works just fine.

Is this normal?
David Lowndes - 09 Oct 2007 10:26 GMT
>Note that although this involves SAPI, it is more a question about Timers
>and event handlers.
>
>I wrote a Speech Recognize handler (SAPI), and put some code in it to enable
>a Timer. It would not do it. If I bring this same code outside this event
>handler, it works just fine.

And the code you've used it what?

You need to tell us a bit more!

Dave
Peter Oliphant - 09 Oct 2007 18:08 GMT
I wish this newsgroup had an ability to at least attach a text file with
code. My code to demonstrate this situation is too long, and this newsgroup
tends to reformat the text in a bad way if the line is too long.

But, I'll try to explain it a bit more. Assume in the following that 'timer'
is set up with an interval and event handler:

System::Windows::Forms::Timer^ timer = gcnew Timer() ;

void Handler( Object^, SpeechRecognizedEventArgs^ e )
{
    timer->Enable ; // problem!
}

That is, if I try to launch a timer inside the 'recognized speech' handler
it doesn't enable the timer. I believe it also locks out the timer from then
on (timer no longer responds to any commands). If this code is placed
outside of the handler, it launches the timer just fine.

FYI, using MS VS VC++ 2008 Express (Beta 2) with .NET Framework 3.5 on a
Vista machine. (SAPI 5.3 ala Vista). Managed (/cli) code generation.

I have a workaround, but it's not wonderful. I create an external 'master'
timer that polls whether other timers should be turned on via their
individual flags, and then set the flag of the timer to be launched in the
above handler instead. The disadvantage of course is that this adds an
unpredictable additonal lag (since it can make the request by setting the
timer flag at any point in the master timer's interval), although it is
short by human terms.

I tried moving this to the Recognition Completed handler of the speech
recognizer thinking perhaps it was the extensive recognition processing that
caused the problem. But that handler won't launch a timer either.

Hope that helps in the info department. This could be a problem or a
feature. If a problem, it could be part of SAPI or VC++.It could be a bug in
my code, but I've seen this happen two different ways (or NOT happeneing, if
you will), so this is not likely.  I'm wondering if it is just disallowed in
general to launch a System Timer from an (any?) event handler. Can a Timer
handler launch another Timer, for instance?

Don't hesitate to ask if you want some specific questions asked...

Thanks!

[==Peter==]

> >Note that although this involves SAPI, it is more a question about Timers
>>and event handlers.
[quoted text clipped - 9 lines]
>
> Dave
David Lowndes - 09 Oct 2007 18:33 GMT
>But, I'll try to explain it a bit more. Assume in the following that 'timer'
>is set up with an interval and event handler:
[quoted text clipped - 4 lines]
>{
>     timer->Enable ; // problem!

Is that actually:
    timer->Enabled = true;
?

>That is, if I try to launch a timer inside the 'recognized speech' handler
>it doesn't enable the timer.

Is there any sign of an exception being raised in the output window?

>If this code is placed
>outside of the handler, it launches the timer just fine.

So are you saying that if you just call timer->Enabled = true; for
that same timer object from elsewhere in your code (with no other
changes), it's OK? I'm stumped in that case. I don't know enough about
the timer implementation to offer an explanation of that behaviour.

Dave
Peter Oliphant - 09 Oct 2007 20:13 GMT
> Is that actually:
> timer->Enabled = true;

yup, typo. Not lifted from my code since it's too big, so I just did that
from memory. :)

> Is there any sign of an exception being raised in the output window?

Nope, it just does nothing. However, future attempts to use the timer no
longer work from anywhere.

> So are you saying that if you just call timer->Enabled = true; for
> that same timer object from elsewhere in your code (with no other
> changes), it's OK? I'm stumped in that case. I don't know enough about
> the timer implementation to offer an explanation of that behaviour

Yup. One possibility is this is just not allowed. An event is probably
similar to an 'interrupt', and some things can be dangerous if launched from
them. That's my guess.

I might try to write a truly reduced version of this behavior and post the
results to make sure it's not ME... :)

[==Peter==]

> >But, I'll try to explain it a bit more. Assume in the following that
> >'timer'
[quoted text clipped - 24 lines]
>
> Dave
William DePalo [MVP VC++] - 09 Oct 2007 19:19 GMT
> Hope that helps in the info department. This could be a problem or a
> feature. If a problem, it could be part of SAPI or VC++.It could be a bug
> in my code, but I've seen this happen two different ways (or NOT
> happeneing, > if you will), so this is not likely.  I'm wondering if it is
> just disallowed in general to launch a System Timer from an (any?) event
> handler. Can a Timer handler launch another Timer, for instance?

I'd bet a few cents that the "bug" is not in SAPI. Of course, I could be
wrong.

I don't know that it is your problem, but every time that I've seen people
report "problems" in the SAPI groups with "events" not firing it has to do
with the fact that the host application does not pump messages. Underlying
SAPI is all that COM gunk which persists in using window messages as an IPC
mechanism in the 21st century which I think (I should point out that I'm on
the lunatic fringe*) should have gone out with 16 bit Windows.

That said, I don't know what the speech classes in the .Net framework do.
Mine wrap native C++/Win32 code. ;-)

Regards,
Will
www.ivrforbeginners.com

* In my own native SAPI applications I use a Win32 synchronization object -
an event handle - to signal the completion of operations so that I don't
have to punp messages. It's a lot more work.
Peter Oliphant - 09 Oct 2007 20:25 GMT
> I'd bet a few cents that the "bug" is not in SAPI. Of course, I could be
> wrong.

I've programmed long enough that I have the exact same instincts. I first
and foremost assume it's a problem either with a bug/typo in my code or a
misconception on my part (usually due to incomplete information on the
subject).

But this seems pretty cut and dried. I took the code that the event executes
(which I saw it get to ala a breakpoint experiment), took it outside the
event, and it worked perfectly. Inside, it doesn't launch the timer and the
timer no longer works. And no errors are ever reported in build or
execution.

It just might be a restrictions to what can be done in an event (since it is
like an interrupt). But it seems kind of weird that a Timer can't be
launched from event handlers (maybe any event handler, anyone have a
counter-example?). The only thing that makes me wonder about this is that no
errors are ever reported and it hangs the timer instead of doing absolutely
nothing. If this was intended behavior (on non-behavior if you will), I
would think it would do one or not the other.

Tonight I might build a tiny project that demonstrates this behavior, and
I''ll report back if this is true or if I'm an idiot (of course those are
not mutually exclusive possibilities...lol)...

[==Peter==]

>> Hope that helps in the info department. This could be a problem or a
>> feature. If a problem, it could be part of SAPI or VC++.It could be a bug
[quoted text clipped - 23 lines]
> object - an event handle - to signal the completion of operations so that
> I don't have to punp messages. It's a lot more work.
Ben Voigt [C++ MVP] - 09 Oct 2007 15:40 GMT
> Note that although this involves SAPI, it is more a question about Timers
> and event handlers.
[quoted text clipped - 4 lines]
>
> Is this normal?

Which "Timer"?  .NET has at least three different classes named Timer.
Peter Oliphant - 10 Oct 2007 04:33 GMT
OK, I've duplicated the problem in a little bit of code. I've put it below,
you must excuse any line-wrap.

If you want to see, create a console project.Place the code I have below the
Project.CPP file (the one with main()).

Be sure to add System.Speech as a reference, and set it up tp target .NET
Framework 3.5. This code will also likely only work on a Windows VISTA
machine (SAPI 5.3).

Describing the code:

In a 'globals' class it creates a Timer and a SpeechRecognitionEngine (that
recognizes 'yes' or  'no'). Say 'yes' or 'no' into the microphone, and he
Engine's Completed handler writes 'enable timer' to the console and enables
the timer. The Timer should after that write 'tick!' to the display 4 times
a second after that.

What happens is that you will see the 'enable timer' message, proving the
Completed handler fired and enabled Timer, but the 'Tick's never show up
indicating the Timer never fires!

Thus, whether a restriction or a bug, a Timer can't be enabled successfully
in any Speech Recognition event handler (this happens with all of them, I'm
just demonstrting Completed here).

Here is the code:

//------------------------

#include "stdafx.h"

#using <mscorlib.dll>
#using <System.DLL>
#using <System.Windows.Forms.DLL>

using namespace System::Windows::Forms ;
using namespace System ;
using namespace System::Speech::Recognition ;

typedef EventHandler<RecognizeCompletedEventArgs^> Speech_Completed_Handler
;
typedef System::Windows::Forms::Timer              System_Timer    ;

ref class globals
{
public:
static globals()
{
Timer  = gcnew System::Windows::Forms::Timer() ;
Timer->Tick += gcnew EventHandler(&globals::Tick_Handler ) ;
Timer->Interval = 100 ;
Engine = gcnew SpeechRecognitionEngine() ;
Engine->SetInputToDefaultAudioDevice() ;
Engine->RecognizeCompleted += gcnew Speech_Completed_Handler(
&globals::Completed_Handler ) ;
Choices^ choices = gcnew Choices ;
choices->Add( "yes" ) ;
choices->Add("no" ) ;
Grammar^ grammar = gcnew Grammar(choices) ;
Engine->LoadGrammar(grammar) ;
}

static void Completed_Handler(Object^,RecognizeCompletedEventArgs^)
{
Console::WriteLine( "enable timer" ) ;
Timer->Enabled = true ;
}

static void Tick_Handler( System::Object^,EventArgs^ )
{
Console::WriteLine( "tick!" ) ;
}

static SpeechRecognitionEngine^ Engine ;
static  System::Windows::Forms::Timer^ Timer ;
} ;

int main(array<System::String ^> ^args)
{
Console::WriteLine("Speak!");
globals::Engine->RecognizeAsync() ;
Form^ form = gcnew Form() ;
Application::Run( form ) ;
return 0;
}

//------------------------

[==Peter==]

>> Note that although this involves SAPI, it is more a question about Timers
>> and event handlers.
[quoted text clipped - 6 lines]
>
> Which "Timer"?  .NET has at least three different classes named Timer.
Peter Oliphant - 10 Oct 2007 04:41 GMT
I've noticed something, so here's some more info on the behavior. This
message comes up in the Ouput window instead of the Timer firing:

"Loaded 'C:\Windows\System32\msxml3.dl"
"First-chance exception at 0x7611b09e in PAO_Recognition_Quirk.exe:
0x0000071A: The remote procedure call was cancelled."

[PAO_Recognition_Quirk.exe is the exacutable file's name for the project]

which I believe this is somehow telling me that my Timer is no-workie... :)

[==Peter==]

> OK, I've duplicated the problem in a little bit of code. I've put it
> below, you must excuse any line-wrap.
[quoted text clipped - 97 lines]
>>
>> Which "Timer"?  .NET has at least three different classes named Timer.
David Lowndes - 10 Oct 2007 09:38 GMT
>I've noticed something, so here's some more info on the behavior. This
>message comes up in the Ouput window instead of the Timer firing:
>
>"Loaded 'C:\Windows\System32\msxml3.dl"
>"First-chance exception at 0x7611b09e in PAO_Recognition_Quirk.exe:
>0x0000071A: The remote procedure call was cancelled."

Is the SAPI callback run on a different thread perhaps?

Dave
Peter Oliphant - 10 Oct 2007 15:54 GMT
"> Is the SAPI callback run on a different thread perhaps?"

The code I listed is the entire program. I didn't setup anything specific
except making sure it targets .NET Framework 3.5 and making System::Speech a
reference. And this must be run on a machine using Windows Vista, but might
work on an XP machine for which SAPI has been manually installed.

So to answer your question, I don't really know, but I didn't write anything
special to run it in a separate thread if that is what is happening.

[==Peter==]

> >I've noticed something, so here's some more info on the behavior. This
>>message comes up in the Ouput window instead of the Timer firing:
[quoted text clipped - 6 lines]
>
> Dave
David Lowndes - 10 Oct 2007 16:34 GMT
>"> Is the SAPI callback run on a different thread perhaps?"
>
>So to answer your question, I don't really know

You can find out if you run it under the debugger and check what
thread is active when you hit the callback.

I was offering it as a suggestion as to the cause of the error which I
originally suspected might have been showing up in the output window.

Dave
Peter Oliphant - 10 Oct 2007 17:26 GMT
> You can find out if you run it under the debugger and check what
> thread is active when you hit the callback.

Where do I look in the GUI (during a debug session) to find this
information? How is a thread identified/distinguished (to determine 'what
thread' I need to know how a thread is represented: thread 1?  thread A?
thread ???), Should I set a breakpoint in the callback and then look for it?
And I assume you mean the RecognitionCompleted callback since the Tick
callback never fires.

Can't do this till I get home tonight since my work computer isn't a Vista
machine... :)

> I was offering it as a suggestion as to the cause of the error which I
> originally suspected might have been showing up in the output window.

Cool. And thanks for taking the time to respond, too! :)

[==Peter==]

> >"> Is the SAPI callback run on a different thread perhaps?"
>>
[quoted text clipped - 7 lines]
>
> Dave
David Lowndes - 10 Oct 2007 20:15 GMT
>Where do I look in the GUI (during a debug session) to find this
>information? How is a thread identified/distinguished (to determine 'what
>thread' I need to know how a thread is represented: thread 1?  thread A?
>thread ???), Should I set a breakpoint in the callback and then look for it?

Yes, that's right - use the Threads pane.

>And I assume you mean the RecognitionCompleted callback since the Tick
>callback never fires.

Yes - that's where I'd assume setting the Enabled property might be
throwing an exception.

Dave
Ben Voigt [C++ MVP] - 10 Oct 2007 20:26 GMT
> OK, I've duplicated the problem in a little bit of code. I've put it
> below, you must excuse any line-wrap.
[quoted text clipped - 17 lines]
> Completed handler fired and enabled Timer, but the 'Tick's never show up
> indicating the Timer never fires!

What if you enable the Timer before starting recognition?  Do ticks stop
arriving when you enable the recognition engine?  Could your tick handler
check a shared variable and immediately return in order to emulate disabling
the timer?

> Thus, whether a restriction or a bug, a Timer can't be enabled
> successfully in any Speech Recognition event handler (this happens with
[quoted text clipped - 75 lines]
>>
>> Which "Timer"?  .NET has at least three different classes named Timer.
Peter Oliphant - 10 Oct 2007 21:34 GMT
>What if you enable the Timer before starting recognition?  Do ticks stop
>arriving when you enable the recognition engine?

The Timer runs fine unless I try to use it in the event handler. That is,
any running Timer is not effected by the recognition event handler firing,
but trying to do something with a Timer inside such a handler does.

>Could your tick handler check a shared variable and immediately return in
>order to emulate disabling the timer?

Indeed, this is how I do it. But of course this isn't as immediate, but so
far works for my purposes. While this is a 'work around' that works, it
still seems odd that one can't launch (i.e., enable successfully) a Timer
inside recognition handlers. If this is a bug, I'd rather not have to create
the delayed infostructure I have and enable the Timer directly. If this is a
'feature' (ala it is intended behaviour), then I'll stick with the work
around.

[==Peter==]

>> OK, I've duplicated the problem in a little bit of code. I've put it
>> below, you must excuse any line-wrap.
[quoted text clipped - 102 lines]
>>>
>>> Which "Timer"?  .NET has at least three different classes named Timer.
Ben Voigt [C++ MVP] - 10 Oct 2007 22:13 GMT
> >What if you enable the Timer before starting recognition?  Do ticks stop
> >arriving when you enable the recognition engine?
[quoted text clipped - 13 lines]
> this is a 'feature' (ala it is intended behaviour), then I'll stick with
> the work around.

Could you print out the value of the InvokeRequired property of your timer,
seen inside the recognition handler?

> [==Peter==]
Peter Oliphant - 12 Oct 2007 00:06 GMT
I've been using System::Windows::Forms::Timer, which doesn't have an
'InvokeRequired' property.

I'm thinking I'm using the wrong Timer class. I'll look for others in MSDN.
Not sure how to look up different classes with the same name though. The one
I use isn't managed. I'd rather use a managed one, as long as it can have an
Interval in milliseconds, a means to turn it on and off, and a way to give
it an event handler (hopefully via delegates).

Not sure that has anything to do with it, but it could...

[==Peter==]

>> >What if you enable the Timer before starting recognition?  Do ticks stop
>> >arriving when you enable the recognition engine?
[quoted text clipped - 19 lines]
>
>> [==Peter==]
Peter Oliphant - 12 Oct 2007 00:31 GMT
YEAH! Indeed, everyone in this newsgroup pointed (ok pushed..hehe) me into
the right direction.

If I use this Timer:

System::Timers::Timer     it all works.

If I use:

System::Windows::Form::Timer     it doesn't.

Only difference in implementation is one uses a Tick event the other an
Elapsed event (and corresponding different event hadler forms ala different
argument types). Mixing managed and unmanaged can have some unpredictable
side-effects!

And I think this might solve another problem I just realized could be
related!

Thanx everyone. It works now...

[==Peter==]
> I've been using System::Windows::Forms::Timer, which doesn't have an
> 'InvokeRequired' property.
[quoted text clipped - 32 lines]
>>
>>> [==Peter==]
Peter Oliphant - 12 Oct 2007 01:09 GMT
I  reported success a bit too soon.

It worked in the simple case. But I'm seeing a lot of thread conflicts
(Output messages) now. And a LOT more is being loaded in at startup.

I think I'm running into conflicts between the voice recognition engine SAPI
and the Timers. Or they are somehow interfering with themselves (my simple
case only had one timer that went when voice recognition was done). I'll
keep experimenting...

[==Peter==]

> YEAH! Indeed, everyone in this newsgroup pointed (ok pushed..hehe) me into
> the right direction.
[quoted text clipped - 54 lines]
>>>
>>>> [==Peter==]
Peter Oliphant - 12 Oct 2007 02:34 GMT
Sorry for all the messages, but I think I FINALLY have it all sorted out.

I have to use System::Windows::Form::Timer class timers if their handlers
will manipulate controls and graphics on Forms.

I must use System::Timeers::Timer class timers if I want to launch Speech
Recognition from their event handlers.

You can see how this was confusing, especially since they have the same name
and almost the same structure (but thank goodness for the last one,
conversion was easier because of it).

I now have my own Timer class that uses which ever type, defined upon
creation (poiner to both types internally, use only one for any instance).

As always, I learned a LOT about stuff this way!!! :)

[==Peter==]
>I  reported success a bit too soon.
>
[quoted text clipped - 67 lines]
>>>>
>>>>> [==Peter==]
Andrew Thompson - 12 Oct 2007 03:36 GMT
> OK, I've duplicated the problem in a little bit of code. I've put it below,
> you must excuse anyline-wrap.

Why make excuses?

Here is a simple tool* that will check line width
<http://www.physci.org/twc.jnlp>

* Uses the Java Plug-In - sandboxed (like an average
applet on a web page).

Andrew T.
Peter Oliphant - 10 Oct 2007 05:17 GMT
"Which "Timer"?  .NET has at least three different classes named Timer. "

I got to thinking. Maybe this is the problem. Maybe I'm using the wrong
flavor of Timer. I'm using the System::Windows::Form::Timer, which now that
I think of it, is an 'old' Timer class.

Is there maybe a new-and-improved managed Timer class I should look at? I
All I need is one I can enable and disable, set its interval in
milliseconds, and for it to have tick event. I guess to distinguish it I
need it's full 'namespace' and any headers required.

Thanks!

[==Peter==]

[==Peter==]

>> Note that although this involves SAPI, it is more a question about Timers
>> and event handlers.
[quoted text clipped - 6 lines]
>
> Which "Timer"?  .NET has at least three different classes named Timer.

Free Magazines

Get these publications absolutely FREE for up to 12 months. There are no hidden fees and no obligation. Simply choose a title, complete the application form and submit it. Read more ...

Oracle MagazineNetwork ComputingComputer WorldBio-IT WorldeWeekInformation WeekInfosecurity
 
Sign In
Join
My Latest Posts
My Monitored Threads
My Blog
My Photo Gallery
My Profile
My Homepage

Start New Thread
Enable EMail Alerts
Rate this Thread



©2008 Advenet LLC   Privacy Policy - Terms of Use
This website includes both content owned or controlled by Advenet as well as content owned or controlled by third parties.