在 Xamarin 中锁定 TTS 方法

问题描述 投票:0回答:1

我正在 Xamarin 中编写一个应用程序。我正在使用 Azure 的 TTS 服务。我有两种不同的方法。两种方法都使用 TTS。但我不希望其中一个在另一个完成之前使用它。我该怎么做?

这是主法师:

namespace PorjectB1.Controller
{
    public partial class MainPage : ContentPage
    {
        private System.Timers.Timer m1Timer;
        private System.Timers.Timer m2Timer;
        static Model.TextToSpeech ttsService = new Model.TextToSpeech();

        public MainPage()
        {
            InitializeComponent();
            m1Timer= new System.Timers.Timer(15000);
            m1Timer.Elapsed += OnM1TimerElapsed;
            m1Timer.AutoReset = true;
            m1Timer.Enabled = true;
            m2Timer = new System.Timers.Timer(60000);
            m2Timer.Elapsed += OnM2Elapsed;
            m2Timer.AutoReset = true;
            m2Timer.Enabled = true;
        }

        private void OnM1TimerElapsed(object sender, ElapsedEventArgs e)
        {
            M1(this);
        }
        private void OnM2Elapsed(object sender, ElapsedEventArgs e)
        {
            M2(this);
        }

        private async void M1(object sender, EventArgs e)
        {
             string SpeechText=string.Empty;
             //Do Something...
             Speak(SpeechText); 
        }

        private async void M2(object sender, EventArgs e)
        {
            string SpeechText=string.Empty;
             //Do Something...
             Speak(SpeechText);  
        }

        private void Speak(string text)
        {
             ttsService.Speak(text);
        }
    }
}

这是 TTS 服务类:


using Microsoft.CognitiveServices.Speech;

namespace PorjectB1.Model
{
    public class TextToSpeech
    {
        static private string speechKey { get; set; }
        static private string speechRegion { get; set; }
        
        public TextToSpeech()
        {
            speechKey = "***";
            speechRegion = "***";
        }

        static void OutputSpeechSynthesisResult(SpeechSynthesisResult speechSynthesisResult, string text)
        {
            switch (speechSynthesisResult.Reason)
            {
                case ResultReason.SynthesizingAudioCompleted:
                    //Log Something
                    break;
                case ResultReason.Canceled:
                    //Log Something
                    break;
                default:
                    //Log Something
                    break;
            }
        }

        public async void Speak(string text)
        {
            var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);

            using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
            {
                var speechSynthesisResult = await speechSynthesizer.SpeakTextAsync(text);
                OutputSpeechSynthesisResult(speechSynthesisResult, text);
            }

        }
    }
}

我在主页 Speak 方法上尝试了 Lock、Monitor 和 SemaphorSlim 来解决这个问题。

multithreading azure xamarin xamarin.forms text-to-speech
1个回答
0
投票

为了确保 Xamarin 应用程序中的一个文本转语音 (TTS) 方法不会在另一个方法完成之前启动,使用 SemaphoreSlim 等同步技术是一种很好的方法。您似乎已经尝试过使用 Lock、Monitor 和 SemaphoreSlim,但让我们根据您的用例使用 SemaphoreSlim 改进实现。

SemaphoreSlim 非常适合这种情况,因为它提供了一种等待异步操作的方法,同时限制可以同时访问资源或资源池的线程数量。

以下是修改 MainPage 和 TextToSpeech 类以使用 SemaphoreSlim 的方法:

定义一个 SemaphoreSlim:在 MainPage 类中,定义一个初始计数为 1 的 SemaphoreSlim。这意味着一次只有一个线程可以进入临界区。

private SemaphoreSlim semaphoreSlim = new SemaphoreSlim(1, 1);

修改 Speak 方法:在 TextToSpeech 类的 Speak 方法中,使用 semaphoreSlim.WaitAsync() 和 semaphoreSlim.Release() 包装 TTS 逻辑以确保同步。

    public class TextToSpeech
{
    // ... existing fields and constructor ...

    public async Task Speak(string text)
    {
        await semaphoreSlim.WaitAsync();
        try
        {
            var speechConfig = SpeechConfig.FromSubscription(speechKey, speechRegion);
            using (var speechSynthesizer = new SpeechSynthesizer(speechConfig))
            {
                var speechSynthesisResult = await speechSynthesizer.SpeakTextAsync(text);
                OutputSpeechSynthesisResult(speechSynthesisResult, text);
            }
        }
        finally
        {
            semaphoreSlim.Release();
        }
    }
}

将 SemaphoreSlim 传递给 TTS 服务:将 semaphoreSlim 实例传递给 TextToSpeech 服务,以便它可以使用它进行同步。

static Model.TextToSpeech ttsService = new Model.TextToSpeech(semaphoreSlim);

调整TextToSpeech中的构造函数:修改TextToSpeech的构造函数以接受SemaphoreSlim参数。

    public TextToSpeech(SemaphoreSlim semaphore)
{
    speechKey = "***";
    speechRegion = "***";
    this.semaphoreSlim = semaphore;
}

通过这些更改,您的 TTS 方法将同步 - 当 M1 调用 TTS 时,M2 将等待 M1 完成后再开始,反之亦然。这可确保两种方法不会同时调用 TTS 服务。

© www.soinside.com 2019 - 2024. All rights reserved.