Search code examples
c#naudio

await Task.Run isn't working inside void?


I am trying to run a "await Task.Run" on my waveOut.play(). The reason is why i want to do this is because i need to delete the file right after waveOut.play() is finished. However, i can not delete something which is already in use, that is why i need to use await task.run but it seems like it isn't working this time. This may be a duplicate but i cant find any reason to why the program isnt waiting for it to finish.

    public async void PlayAudio(object sender, GenericEventArgs<Stream> args)
    {
        fileName = $"{ Guid.NewGuid() }.wav";
        using (var file = File.OpenWrite(Path.Combine(Directory.GetCurrentDirectory(), fileName)))
        {
            args.EventData.CopyTo(file);
            file.Flush();
        }
        WaveOut waveOut = new WaveOut();
        WaveFileReader reader = new WaveFileReader(fileName);
        waveOut.Init(reader);
        try
        {
            await Task.Run(() =>
            {
                waveOut.Play();
            });

        }
        finally
        {
            File.Delete(fileName);
        }

    }

The program finds the file by string name and plays it. The await task.run isn't working here. It jumps straight down to the finally block.


Solution

  • The problem is that WaveOut.Play() returns immediately. Straight from the NAudio documentation (emphasis mine):

    Starting playback

    Now we're ready to begin playback, and we can do so by simply calling Play on our output device. It's important to note that this is not a blocking call. It just begins playback. If you want to be notified when playback ends, we'll discuss how to do that shortly.

    waveOut.Play();
    

    Thus, your Task is completing immediately without waiting for the clip to be played. The NAudio documentation continues:

    Stopping playback

    By default, the output device (WaveOutEvent in our case) will keep playing until we reach the end of the input stream we passed into Init. This is indicated when the IWaveProvider.Read method returns 0. Assuming you passed in an Mp3FileReader or another file reader, then your file will eventually reach the end.

    You can get notification that playback has finished by subscribing to the PlaybackStopped event. This event will also be able to tell you if playback has stopped due to an error with the soundcard. For example, if your device is a USB headset and you unplug it midway through playing, then you will see one of these errors.

    waveOut.PlaybackStopped += OnPlaybackStopped;
    

    You can of course request that playback stops at any time by calling Stop. Note that playback may not actually have stopped when this method exits. You've simply requested that playback stops, and it normally happens very quickly. But only when you get the PlaybackStopped event can you be sure it has completely stopped.

    waveOut.Stop();