在更新 WPF 组件时如何暂停主线程?

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

我正在尝试更新文本框以显示 3-2-1,然后播放声音。这有点有效,但我的声音立即开始播放,因为线程没有阻塞主线程。我尝试添加另一个 Thread.Sleep(4000);在他的主线程中,但是一切都只是等待并且文本框不显示运行数字。我在文本框中输入数字 1 并且播放声音:(

那么如何暂停主线程,同时 TextBox 运行 3-2-1 然后发出声音?

´´´ private void Button_Click(对象发送者, RoutedEventArgs e) {

try
{

    ThreadPool.QueueUserWorkItem(async (o) =>

{ Dispatcher.Invoke((Action)(() => outputTextBox.Text = "3"));

await Task.Delay(1000);
Dispatcher.Invoke((Action)(() => outputTextBox.Text = "2"));
await Task.Delay(1000);
Dispatcher.Invoke((Action)(() => outputTextBox.Text = "1"));
await Task.Delay(3000);

});

任务.延迟(3000);

    if (waveOut!=null ) waveOut.Stop(); 

    Songs = db.Songs; 
    int r = rnd.Next(Songs.Count);

    System.Diagnostics.Debug.WriteLine(r);

    String name = ((Song)Songs[r]).Name1;
    System.Diagnostics.Debug.WriteLine(name);

    int start = ((Song)Songs[r]).Start1;
    System.Diagnostics.Debug.WriteLine(start);

    waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
    

    var ms = File.OpenRead("C:\\"+name);
    var rdr = new Mp3FileReader(ms);
    var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr);
    wavStream.Skip(start);
    var baStream = new BlockAlignReductionStream(wavStream);
    
    waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());
    
        waveOut.Init(baStream);

    
    
    waveOut.Play();
        
    /*
        while (waveOut.PlaybackState == PlaybackState.Playing)
        {
            Thread.Sleep(100);
        }
      */  
    
}
catch (Exception ex)
{
    MessageBox.Show(ex.Message);
    return;
}

}

´´´

wpf
2个回答
1
投票

使用

async
关键字标记您的事件处理程序,并在播放声音之前等待
Delay
调用:

private async void Button_Click(object sender, RoutedEventArgs e)
{
    try
    {
        outputTextBox.Text = "3";
        await Task.Delay(1000);
        outputTextBox.Text = "2";
        await Task.Delay(1000);
        outputTextBox.Text = "1";
        await Task.Delay(1000);

    // play sound:

        if (waveOut!=null)
            waveOut.Stop();

        Songs = db.Songs;
        int r = rnd.Next(Songs.Count);

        System.Diagnostics.Debug.WriteLine(r);

        String name = ((Song)Songs[r]).Name1;
        System.Diagnostics.Debug.WriteLine(name);

        int start = ((Song)Songs[r]).Start1;
        System.Diagnostics.Debug.WriteLine(start);

        waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());


        var ms = File.OpenRead("C:\\"+name);
        var rdr = new Mp3FileReader(ms);
        var wavStream = WaveFormatConversionStream.CreatePcmStream(rdr);
        wavStream.Skip(start);
        var baStream = new BlockAlignReductionStream(wavStream);

        waveOut = new WaveOut(WaveCallbackInfo.FunctionCallback());

        waveOut.Init(baStream);

        waveOut.Play();

    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
        return;
    }
}

这里没有理由涉及线程池。


1
投票

正如评论中提到的,只需使用async 和await。我强烈建议您阅读有关它的文档,因为您似乎对其使用感到困惑。

private async void Button_Click(object sender, RoutedEventArgs e) 
{
    try
    {
        // The await call will make it wait until the task is completed
        // (including the delay of 3 seconds) then it will resume the execution
        // of the code after the `await`. 
        outputTextBox.Text = "3";
        await Task.Delay(1000);
        outputTextBox.Text = "2";
        await Task.Delay(1000);
        outputTextBox.Text = "1";
        await Task.Delay(1000);

        this.PlaySong();
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

async
await
的有趣之处在于它不会暂停主线程,因此您的应用程序不会显得无响应。

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