Search code examples
wpf

how can I pause the main thread, while I am updating my WPF components?


I am trying to update a TextBox to display 3-2-1 and then I play a sound. This works sort of, but my sound starts to play immediately, because the Threads are not blcoking the main thread. I tried to add another Thread.Sleep(4000); in he main thread, but then it all just waits and the textbox does not display running numbers. I get number 1 in the textbox and the sound plays :(

So how do I pause the main thread, while the TextBox runs 3-2-1 and then sound?

´´´ private void Button_Click(object sender, 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);

});

Task.Delay(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;
}

}

´´´


Solution

  • Mark your event handler with the async keyword and await the Delay calls before you play the sound:

    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;
        }
    }
    

    There is no reason to involve the thread pool here.