You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 06:16:25