避免执行重叠

时间:2016-04-12 04:00:06

标签: vb.net

我有这段代码:

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事件被触发时,音频重叠 - 我不希望这种情况发生。

任何人都可以告诉我如何避免这种情况?

3 个答案:

答案 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线程。希望这有帮助!