System.Speech.Synthesis.SpeechSynthesizer方法抛出“异步操作此时无法启动”异常。“

时间:2018-04-17 11:00:30

标签: c# asp.net-mvc asynchronous asp.net-web-api system.speech.recognition

这个问题非常类似于(未答复的)问题: SpeechSynthesizer in ASP.NET - async error

我正在尝试在ASP MVC项目中使用System.Speech方法但是如果我这样做:

[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;
}

只要调用GetInstalledVoices,页面就会抛出:

  

此时无法启动异步操作。异步操作只能在异步中启动   处理程序或模块或在页面生命周期中的某些事件期间。如果   执行页面时发生此异常,确保页面   标记为<%@ Page Async =“true”%>。此异常也可能表明   尝试调用“异步void”方法,这通常是   ASP.NET请求处理中不受支持。相反,   异步方法应该返回一个Task,并且调用者应该等待   它。

但我在控制器内部做的事情都是异步的!我无法等待或在控制器内部调用Result。如果我从Web API控制器执行几乎完全相同的操作,那就更奇怪了:

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

然后,当我调用API方法时,它首先工作并返回所有信息,但是如果我再次调用它,那么页面就会挂起来永远加载。 如果我使用其他方法,例如只调用synt.Speak:

,就会发生同样的事情
var synt = new System.Speech.Synthesis.SpeechSynthesizer();
synt.Speak("Hello");

尽管docummentation明确指出Speak方法“同步说出一个字符串的内容。”,这几行代码足以激发所提到的行为(我知道我应该“说话”到一个流,但是这样这不是重点)。 这里发生了什么事??是否可以在ASP MVC中使用System.Speech?

编辑1 好的,我知道如果我将Controller Action转换为async返回一个Task它不会抛出错误(因为异常要求我这样做),但它似乎我只是一种规避问题的方法。我为什么要这样做?它正在谈论的异步操作在哪里?让我感到困惑的是,如果代码真的是同步的(因为它在文档中明确说明)为什么这是必要的?实际上,如果代码是同步的,我也应该能够这样做:

[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;
}

当我这样做时,它在第一个请求上工作,然后它显然随机抛出异常。在我看来,在调用GetInstalledVoices之后,在后台留下了“某些东西”,只需返回任务就可以解决问题。

编辑2 https://weblogs.asp.net/ricardoperes/speech-synthesis-with-asp-net-and-html5中阅读:

  

我们需要设置一个同步上下文,因为SpeechSynthesizer异步工作,所以我们可以等待它的结果

我试过了:

[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;
    }
}

现在它正在发挥作用。但老实说,我不知道为什么,我不知道是否还有其他后果要做到这一点。任何有关此事的亮点都将受到赞赏。

0 个答案:

没有答案