C#任务 - 我是否经历了可疑的句柄数量增加

时间:2014-11-18 09:16:04

标签: c# async-await task

我在任务(.NET 4.5)中蘸了我的脚趾,并且正在经历增加的句柄(在任务管理器中)。我有一个类使用MediaPlayer类(System.Windows.Media命名空间)进行简单的播放/停止音频文件。我有第二个包装它并暴露同步/异步播放的类。 一切正常,功能还可以,但是看到任务管理器中增加的句柄数量令我担心....我在这里做错了吗?

重要提示:如果我评论“await Task.Delay(1000);” - >然后一切都很好,没有发现泄漏......怎么回事?

public partial class Form1 : Form
{
    AudioActions syncAction = new AudioActions(@"c:\1.wav", false);
    AudioActions asyncAction = new AudioActions(@"c:\1.wav", true);

    public Form1()
    {
        InitializeComponent();
    }

    private async void syncPlayback(object sender, EventArgs e)
    {
        for (int i = 0; i < 10; i++)
        {
            await syncAction.Start();
        }
    }

    private async void asyncPlayback(object sender, EventArgs e)
    {
        for (int i = 0; i < 100; i++)
        {
            await asyncAction.Start();
            await Task.Delay(100); //remove this line and all is fine!!!!
            asyncAction.Stop();
        }
        Console.WriteLine("done");
    }
}

public class AudioActions
{
    private Audio audio = null;
    private TaskCompletionSource<bool> tcs = null;
    private string pathToWaveFile;
    private bool async;

    public AudioActions(string pathToWaveFile, bool async)
    {
        this.pathToWaveFile=pathToWaveFile;
        this.async=async;
    }

    public Task Start()
    {
        tcs = new TaskCompletionSource<bool>();
        audio = new Audio();
        audio.mediaPlayerPlaybackStoppedEvent += Audio_wmPlaybackStopped;

        if (async)
            tcs.TrySetResult(true); //since its async operation, lets return immediately and free the task from waiting

        audio.PlayAudioFileInMediaPlayer(pathToWaveFile);
        return tcs.Task;
    }

    private void Audio_wmPlaybackStopped()
    {
        audio.mediaPlayerPlaybackStoppedEvent -= Audio_wmPlaybackStopped;
        tcs.TrySetResult(true); //playback stopped. Lets free the task from waiting
    }

    public void Stop()
    {
        audio.StopAudioFilePlaybackInMediaPlayer();
    }
}

public class Audio
{
    MediaPlayer mediaPlayer = null;

    public delegate void MediaPlayerPlaybackStoppedDelegate();
    public event MediaPlayerPlaybackStoppedDelegate mediaPlayerPlaybackStoppedEvent;

    public void PlayAudioFileInMediaPlayer(string pathToWavFile)
    {
        mediaPlayer = new MediaPlayer();
        mediaPlayer.MediaEnded += mediaPlayer_MediaEnded;
        mediaPlayer.Open(new Uri(pathToWavFile));
        mediaPlayer.Play();
    }

    void mediaPlayer_MediaEnded(object sender, EventArgs e)
    {
        mediaPlayerPlaybackStoppedEvent.Invoke();
        MediaPlayer mediaPlayer = (MediaPlayer)sender;
        mediaPlayer.MediaEnded -= mediaPlayer_MediaEnded;
        mediaPlayer.Close();
        mediaPlayer = null;
    }

    public void StopAudioFilePlaybackInMediaPlayer()
    {
        mediaPlayer.Stop();
        mediaPlayer.Close();
        mediaPlayer = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
    }
}

添加条带代码:

private async void asyncPlayback(object sender, EventArgs e)
{
    AudioActions asyncAction = new AudioActions();
    for (int i = 0; i < 100; i++)
    {
        await asyncAction.Start();
        await Task.Delay(1000); //remove this line and all is fine!!!!
        asyncAction.Stop();
    }
}

public class AudioActions
{
    private Audio audio = null;
    private TaskCompletionSource<bool> tcs = null;

    public Task Start()
    {
        tcs = new TaskCompletionSource<bool>();
        audio = new Audio();
        tcs.TrySetResult(true); //since its async operation, lets return immediately and free the task from waiting

        audio.PlayAudioFileInMediaPlayer(@"c:\1.wav");
        return tcs.Task;
    }

    public void Stop()
    {
        audio.StopAudioFilePlaybackInMediaPlayer();
    }
}

public class Audio
{
    MediaPlayer mediaPlayer = null;

    public void PlayAudioFileInMediaPlayer(string pathToWavFile)
    {
        mediaPlayer = new MediaPlayer();
        mediaPlayer.Open(new Uri(pathToWavFile));
        mediaPlayer.Play();
    }

    public void StopAudioFilePlaybackInMediaPlayer()
    {
        mediaPlayer.Stop();
        mediaPlayer.Close();
        mediaPlayer = null;
        GC.Collect();
        GC.WaitForPendingFinalizers();
        GC.Collect();
    }
}

解决问题的修改过的课程:

public class Audio
{
    public delegate void NaudioPlaybackStoppedDelegate();
    public event NaudioPlaybackStoppedDelegate naudioPlaybackStoppedEvent;

    private WaveOut player = null;

    public void PlayAudioFileUsingNaudio(string pathToWavFile)
    {
        player = new WaveOut();
        AudioFileReader waveFileReader = new AudioFileReader(pathToWavFile);
        player.Init(waveFileReader);
        player.PlaybackStopped += NAudio_Stopped;
        player.Play();
    }

    private void NAudio_Stopped(object sender, StoppedEventArgs e)
    {
        player.PlaybackStopped -= NAudio_Stopped;
        if (naudioPlaybackStoppedEvent!=null)
            naudioPlaybackStoppedEvent.Invoke();
        player.Dispose();
    }

    public void StopAudioFilePlaybackInNaudio()
    {
        player.Stop();
    }
}

1 个答案:

答案 0 :(得分:0)

用NAudio第三方取代MediaPlayer解决了它。

public class Audio
{
    public delegate void NaudioPlaybackStoppedDelegate();
    public event NaudioPlaybackStoppedDelegate naudioPlaybackStoppedEvent;

    private WaveOut player = null;

    public void PlayAudioFileUsingNaudio(string pathToWavFile)
    {
        player = new WaveOut();
        AudioFileReader waveFileReader = new AudioFileReader(pathToWavFile);
        player.Init(waveFileReader);
        player.PlaybackStopped += NAudio_Stopped;
        player.Play();
    }

    private void NAudio_Stopped(object sender, StoppedEventArgs e)
    {
        player.PlaybackStopped -= NAudio_Stopped;
        if (naudioPlaybackStoppedEvent!=null)
            naudioPlaybackStoppedEvent.Invoke();
        player.Dispose();
    }

    public void StopAudioFilePlaybackInNaudio()
    {
        player.Stop();
    }
}