这个问题非常类似于(未答复的)问题: 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;
}
}
现在它正在发挥作用。但老实说,我不知道为什么,我不知道是否还有其他后果要做到这一点。任何有关此事的亮点都将受到赞赏。