我有这段代码:
Private Sub NewRecallLabel_TextChanged(sender As Object, e As EventArgs)
Dim myrecalllabel As Label = TryCast(sender, Label)
Dim SpeechSynthesizer As New SpeechSynthesizer
SpeechSynthesizer.Speak("Ticket number " & TTSTicket & ", please proceed to counter " & TTSCounter)
End Sub
当TextChanged事件触发时,UI会在执行说话代码时冻结。 我知道使用SpeakAsync会解决问题但是当多个TextChanged事件被触发时,音频重叠 - 我不希望这种情况发生。
任何人都可以告诉我如何避免这种情况?
答案 0 :(得分:1)
我们已经确定您正在使用.NET 4.0,因此SemaphoreSlim
会消失。
首先,我尝试通过共享SpeechSynthesizer
的实例并在新请求进入时使用SpeakAsyncCancelAll
来解决问题:
Private SpeechSynthesizer As New SpeechSynthesizer
Private Sub NewRecallLabel_TextChanged(sender As Object, e As EventArgs)
Dim myrecalllabel As Label = TryCast(sender, Label)
SpeechSynthesizer.SpeakAsyncCancelAll()
SpeechSynthesizer.SpeakAsync("Ticket number " & TTSTicket & ", please proceed to counter " & TTSCounter)
End Sub
Oringinal回答
由于您无法在异步上下文中使用SyncLock
并且您希望执行非阻塞,因此最好使用SemaphoreSlim(1, 1)
来获取异步互斥语义(类似于@ Gubr建议,除了异步):
Private Semaphore As New SemaphoreSlim(1, 1)
Private Sub NewRecallLabel_TextChanged(sender As Object, e As EventArgs)
Dim myrecalllabel As Label = TryCast(sender, Label)
Dim SpeechSynthesizer As New SpeechSynthesizer
Await Semaphore.WaitAsync()
Try
' We're inside the protected region now.
Await SpeechSynthesizer.SpeakAsync("Ticket number " & TTSTicket & ", please proceed to counter " & TTSCounter)
Finally
Semaphore.Release()
End Try
End Sub
我还考虑以某种形式的限制和/或自动取消进行连线,因为如果标签文本快速变化(即每个标签文本),代码将会不工作得非常好后续的语音请求必须等待以前的语音请求才能完成。
答案 1 :(得分:0)
也许使用带有异步调用的锁将有助于它看起来像这样:
Private Sub NewRecallLabel_TextChanged(sender As Object, e As EventArgs)
Dim myrecalllabel As Label = TryCast(sender, Label)
Dim SpeechSynthesizer As New SpeechSynthesizer
SpeechSynthesizer.SpeakAsync("Ticket number " & TTSTicket & ", please proceed to counter " & TTSCounter)
End Sub
在您的异步通话中使用lock:
Private messagesLock As New Object
SyncLock messagesLock
SpeechSynthesizer.Speak("the sync one")
End SyncLock
我没有尝试过,但你明白了。
答案 2 :(得分:0)
我能够使用BackgroudWorker
得到我想要的东西。我将SpeakAsync
代码放到BackgroudWorker
并替换了
SpeechSynthesizer.SpeakAsync("Ticket number " & TTSTicket & ", please proceed to counter " & TTSCounter)
与
If SpeechBackgroundWorker.IsBusy = False Then
TTSCounter = CRichTextBox.Text
TTSTicket = TRichTextBox.Text
SpeechBackgroundWorker.RunWorkerAsync()
Exit Sub
End If
它成功地排队了这些演讲并且它不会影响UI线程。希望这有帮助!