C# 事件处理程序如何自动提升自身?
我有两个按钮在我的WPF形式,即播放和前进。“播放”按钮读取文本框中输入的文本,但不能突出显示句子。另一方面,“前进”按钮可以在每次按下时突出显示文本框中输入的文本的一句话 我希望forward按钮事件处理程序在读取一句话时自动启动。在这种情况下,“前进”按钮可以读取一个突出显示的句子,然后可以突出显示第二个句子并读取该句子,依此类推 我不知道如何通过编程自行提升forward按钮事件处理程序C# 事件处理程序如何自动提升自身?,c#,wpf,C#,Wpf,我有两个按钮在我的WPF形式,即播放和前进。“播放”按钮读取文本框中输入的文本,但不能突出显示句子。另一方面,“前进”按钮可以在每次按下时突出显示文本框中输入的文本的一句话 我希望forward按钮事件处理程序在读取一句话时自动启动。在这种情况下,“前进”按钮可以读取一个突出显示的句子,然后可以突出显示第二个句子并读取该句子,依此类推 我不知道如何通过编程自行提升forward按钮事件处理程序 private void btnForward_Click(object sender, Routed
private void btnForward_Click(object sender, RoutedEventArgs e)
{
highlightText();
synth.SpeakAsyncCancelAll();
synth.SpeakAsync(textArea.SelectedText);
//here it should be raised automatically again
}
如果我理解正确,您希望用户只需按一次“前进”按钮。在这之后,程序将自动继续推进文本选择,就像第一次按下按钮一样,并为每个新选择的文本播放语音合成器 如果是这样的话,我相信这是可行的: 我运行了一个小测试,似乎
speakasyncancelall()
方法不会干扰对Speak()
方法的后续调用。此外,我发现它确实会取消同步语音操作(即,它会中断对Speak()
的正在进行的调用)。因此,上述操作肯定可以正常工作,您甚至可以添加一个单独的按钮来取消操作,只需设置一个标志,然后调用speakasyncancelall()
来中断当前的语音操作。从长远来看,更好的解决方案是围绕
SpeechSynthesizer
类实现真正的异步
支持包装器。不幸的是,据我所知,唯一直接支持async
/wait
的语音合成内置实现是SpeechSynthesizer
类的Windows Phone纯版本。但是,您应该能够使用TaskCompletionSource
以及各种SpeechSynthesizer
事件来编写自己的包装器,以允许适合async
/wait
范式的异步方法
请注意,在上面,我禁用了按钮,以便在处理上一次按钮按下时不会再次引发事件。您不希望此代码具有并发迭代,因此我依赖于UI状态来防止在此重新进入
最后要注意的是,上面没有为用户提供任何方式来中断文本选择循环的进程。在你最初的问题中,你没有提供足够的上下文来知道这将如何工作,所以我就把它省略了。但是正如我上面提到的,您可以使用
speakasyncancelall()
方法中断同步语音操作,因此这就像我上面提到的设置标志一样简单,调用cancel方法,然后在上面的循环中检查该标志,查看是否需要提前触发。如果您没有再次实际单击,则再次引发单击事件是没有意义的。但撇开这一点不谈,假设它真的起作用了,会有什么影响呢?将立即选择第二句话,synth.speakasyncancelall()
将取消第一句话。SpeakAsync
的全部要点是,在演讲结束之前,您的代码将继续执行。我认为不会立即选择第二句话,因为synth.SpeakAsync(textArea.SelectedText)代码>使事件等待,直到它读取以前选择的句子。否,它不会。同样,这就是…Async
函数的全部要点:Speak
方法等待。SpeakAsync
方法不等待。文档中也提到了这一点。通过添加像MessageBox.Show(“…”)这样的行,您可以很容易地看到这一点代码>,并检查您是在演讲过程中还是演讲结束后收到消息框。谢谢。我注意到我错了。那么,你对如何完成我的工作有什么想法(如我的问题所述)?我认为基本想法应该是,你要听SpeakCompleted
事件,当发生这种情况时,确定这是否是你的“前进”按钮的结果(这需要你跟踪哪个按钮处于“活动状态”),看看下面是否有一个句子,如果有,选择它并说出来。基本上我正在写一个程序来阅读一些文本。它还应该突出显示它正在阅读的每个句子。用户应该能够前后移动。转发将突出显示并阅读下一个句子,后退则相反。就是这样一个软件的例子。我的程序每次按播放按钮只能读一句文字,但无法继续。
private async void btnForward_Click(object sender, RoutedEventArgs e)
{
btnForward.Enabled = false;
while (true)
{
highlightText();
// NOTE: use whatever expression correctly identifies the state after
// you've called highlightText() when there's no more text to read.
// Here I've assumed that the selection will simply be empty, but
// if that's not right, presumably you have _some_ way to know that
// you're at the end of the text.
if (textArea.SelectedText == "")
{
break;
}
synth.SpeakAsyncCancelAll();
await Task.Run(() => synth.Speak(textArea.SelectedText));
}
btnForward.Enabled = true;
}