Home System.Speech.Synthesis.SpeechSynthesizer methods throw "asynchronous operation cannot be started at this time" exception."
Reply: 0

System.Speech.Synthesis.SpeechSynthesizer methods throw "asynchronous operation cannot be started at this time" exception."

user4599
1#
user4599 Published in April 25, 2018, 12:52 am

This question is very similar to this (unanswered) one: SpeechSynthesizer in ASP.NET - async error

I am trying to use System.Speech methods in an ASP MVC project but if I do something like this:

[HttpGet]
public ActionResult SystemSpeechInstalledVoices()
{
    var synt = new System.Speech.Synthesis.SpeechSynthesizer();
    var voices = synt.GetInstalledVoices();
    var response = Json(voices);
    response.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
    return response;
}

As soon as GetInstalledVoices is called the page throws a:

An asynchronous operation cannot be started at this time. Asynchronous operations may only be started within an asynchronous handler or module or during certain events in the Page lifecycle. If this exception occurred while executing a Page, ensure that the Page is marked <%@ Page Async="true" %>. This exception may also indicate an attempt to call an "async void" method, which is generally unsupported within ASP.NET request processing. Instead, the asynchronous method should return a Task, and the caller should await it.

But nothing I´m doing inside the controller is asynchronous! There is nothing I can wait or call Result on inside the controller. Even stranger, if I do almost exactly the same from a Web API controller:

[HttpGet]
public IHttpActionResult SystemSpeechInstalledVoices()
{
    var synt = new System.Speech.Synthesis.SpeechSynthesizer();
    var voices = synt.GetInstalledVoices();
    var response = Json(voices);        
    return response;
}

Then when I call the API method it works at first and returns all the information, BUT if I call it again then the page just hangs up loading forever. The same thing happens if I use other methods, like just calling synt.Speak:

var synt = new System.Speech.Synthesis.SpeechSynthesizer();
synt.Speak("Hello");

Although the docummentation clearly specifies that Speak method "Synchronously speaks the contents of a string.", this couple of lines of code are enough to provoke mentioned behaviour (I know I should "speak" to a stream, but that´s not the point here). What´s happening here?? Is it possible use System.Speech in ASP MVC?

Edit 1 Ok, I know that if I transform the Controller Action to an async returning a Task it will not throw the error (as the exception is asking me to do), but it seems to me like just a way of circumventing the problem. Why should I have to do that? Where is the asynchronous operation it is talking about? What bugs me is that if the code is really synchronous (as it clearly states in the documentation) why is that necessary?. In fact, if the code is synchronous, I should also be able to do this:

[HttpGet]
public ActionResult SystemSpeechInstalledVoices()
{
    var result = Task.Run(() =>
    {
        using (var synt = new System.Speech.Synthesis.SpeechSynthesizer())
        {
            var voices = synt.GetInstalledVoices();            
            var response = Json("anything");
            response.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
            return response;
        }
    });
    return result.Result;
}

When I do this, it works on a first request and then it apparently randomly throws the exception or not. It seems to me that "something" is left in the background after calling GetInstalledVoices and just returning Task is just sweeping the problem under the carpet.

Edit 2 After reading in https://weblogs.asp.net/ricardoperes/speech-synthesis-with-asp-net-and-html5 that:

we need to set up a synchronization context, because the SpeechSynthesizer works asynchronously, so that we can wait for its result

I have tried:

[HttpGet]
public ActionResult SystemSpeechInstalledVoices()
{
    System.ComponentModel.AsyncOperationManager.SynchronizationContext = new System.Threading.SynchronizationContext();
    using (var synt = new System.Speech.Synthesis.SpeechSynthesizer())
    {
        var voices = synt.GetInstalledVoices();
        var response = Json("anything");
        response.JsonRequestBehavior = JsonRequestBehavior.AllowGet;
        return response;
    }
}

Now it´s working. But honestly I don´know why and I don´t know if there are other consequences to do this. Any light on the matter would be appreciated.

You need to login account before you can post.

About| Privacy statement| Terms of Service| Advertising| Contact us| Help| Sitemap|
Processed in 0.301476 second(s) , Gzip On .

© 2016 Powered by mzan.com design MATCHINFO