ASP MVC中调用SpeechSynthesizer方法抛出异步操作启动异常求助
解决ASP.NET MVC中调用
SpeechSynthesizer.GetInstalledVoices()的异步异常问题 我之前在ASP.NET项目里也踩过这个坑,这个异常本质是ASP.NET的请求同步上下文和SpeechSynthesizer内部的异步逻辑冲突导致的。GetInstalledVoices()方法底层会启动一些异步操作,但ASP.NET的请求线程不允许在当前同步上下文环境中直接发起这类异步操作,所以就抛出了"asynchronous operation cannot be started at this time"的错误。
下面是两种可行的解决方案:
方案一:用Task.Run脱离ASP.NET同步上下文
把语音获取操作放到线程池线程中执行,这样就避开了ASP.NET的同步上下文限制,同时用异步方式处理避免阻塞请求线程:
[HttpGet] public async Task<ActionResult> SystemSpeechInstalledVoices() { // 将操作转移到无同步上下文的线程池线程 var voices = await Task.Run(() => { // 使用using确保SpeechSynthesizer资源被正确释放 using var synt = new System.Speech.Synthesis.SpeechSynthesizer(); return synt.GetInstalledVoices(); }); return Json(voices, JsonRequestBehavior.AllowGet); }
方案二:应用启动时预加载并缓存语音列表
如果服务器上的语音包不会频繁变更,更高效的方式是在应用启动时一次性加载语音列表并缓存,避免每次请求都创建SpeechSynthesizer实例:
第一步:在Global.asax中预加载缓存
// 全局静态变量缓存语音列表 private static List<System.Speech.Synthesis.InstalledVoice> _cachedInstalledVoices; protected void Application_Start() { // 应用启动时加载语音列表,此时无请求上下文限制 _cachedInstalledVoices = Task.Run(() => { using var synt = new System.Speech.Synthesis.SpeechSynthesizer(); return synt.GetInstalledVoices().ToList(); }).Result; // 其他应用初始化代码... }
第二步:在Action中直接返回缓存结果
[HttpGet] public ActionResult SystemSpeechInstalledVoices() { return Json(_cachedInstalledVoices, JsonRequestBehavior.AllowGet); }
注意事项
- 如果后续服务器安装/卸载了语音包,需要重启ASP.NET应用才能刷新缓存;
- 确保应用池的运行身份有足够权限访问系统语音资源(默认的应用池身份一般满足需求,自定义身份需额外检查权限)。
内容的提问来源于stack exchange,提问作者Ada
相关产品推荐
相关产品推荐

