如何在C# GUI中停止文本转语音(TTS)并解决按钮冻结问题
问题解决方案
原代码的核心问题
- 使用
SpeechSynthesizer.Speak()同步方法,会阻塞UI线程,导致按钮冻结,无法在朗读过程中触发停止操作。 - 停止朗读时直接调用
spe.Dispose()销毁合成器,后续无法再次启动朗读。 - 按钮文本切换逻辑依赖同步朗读完成,朗读过程中无法触发停止分支的代码。
修改后的完整代码
using System; using System.Windows.Forms; using System.Speech.Synthesis; namespace TalkBack { public partial class Form1 : Form { private readonly SpeechSynthesizer _speechSynthesizer = new SpeechSynthesizer(); public Form1() { InitializeComponent(); // 订阅朗读完成事件,确保按钮状态正确恢复 _speechSynthesizer.SpeakCompleted += SpeechSynthesizer_SpeakCompleted; } private void SpeechSynthesizer_SpeakCompleted(object sender, SpeakCompletedEventArgs e) { // 朗读完成后将按钮文本改回Speak btn.Text = "Speak"; } private void btn_Click(object sender, EventArgs e) { if (btn.Text == "Speak") { // 切换按钮状态为停止 btn.Text = "Stop"; // 使用异步朗读方法,不阻塞UI线程 string textToSpeak = inputbox.Text.Trim(); if (!string.IsNullOrEmpty(textToSpeak)) { _speechSynthesizer.SpeakAsync(textToSpeak); } else { // 输入为空时恢复按钮状态 btn.Text = "Speak"; MessageBox.Show("请输入要朗读的文本"); } } else { // 停止异步朗读 _speechSynthesizer.SpeakAsyncCancelAll(); // 切换按钮状态为开始 btn.Text = "Speak"; } } protected override void OnFormClosing(FormClosingEventArgs e) { // 窗体关闭时正确释放资源 _speechSynthesizer.Dispose(); base.OnFormClosing(e); } } }
关键改动说明
- 替换同步朗读为异步朗读:使用
SpeakAsync()替代Speak(),避免阻塞UI线程,解决按钮冻结问题,同时允许在朗读过程中点击按钮触发停止操作。 - 正确停止朗读:使用
SpeakAsyncCancelAll()停止所有异步朗读任务,而不是直接销毁合成器,保证后续可以再次启动朗读。 - 订阅
SpeakCompleted事件:确保朗读正常完成后,按钮文本能自动恢复为"Speak",避免状态不一致。 - 添加资源释放逻辑:在窗体关闭时调用
Dispose()释放SpeechSynthesizer资源,符合.NET资源管理规范。 - 增加输入校验:避免空文本导致的无效朗读操作。
内容的提问来源于stack exchange,提问作者MaxMouse
相关产品推荐
相关产品推荐

