播放后强制MediaElement释放流

时间:2013-10-10 11:14:31

标签: c# wpf audio windows-phone-8 wpf-controls

我正在创建一个具有播放功能的录音机控件。

我使用media元素播放录制的音频,如下所示:

using (var storage = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication())
{
    using (System.IO.Stream stream = new System.IO.IsolatedStorage.IsolatedStorageFileStream(filePath, System.IO.FileMode.Open, storage))
    {
        player.SetSource(stream);
    }
}

我面临的问题是当我使用媒体元素播放录制的音频时。流被锁定到媒体元素。

有没有办法强制媒体元素释放流?

4 个答案:

答案 0 :(得分:8)

基于@Sheridan回答这个问题,我想出了它的作用。

每当使用MediaElement函数停止Stop()时,将Source属性设置为null,如下所示:

ResetMediaElement()
{
    mediaElement.Stop();
    mediaElement.Source = null;
}

这将关闭附加到media元素的流,以便相关资源可以在其他地方使用。

答案 1 :(得分:2)

如果你使用MediaElement,请确保你不会被这个: http://msdn.microsoft.com/en-us/library/cc626563(v=vs.95).aspx

  

ArgumentNullException - mediaStreamSource为null   ...

     

调用此方法后,MediaElement.Source返回null。如果这   调用并设置MediaElement.Source,最后一次操作获胜。

     

如果在打开时从UI树中删除了MediaElement   MediaStreamSource,后续对SetSource的调用可能会被忽略。至   确保featureSetSource调用可以正常工作,将Source属性设置为   从UI树中分离MediaElement之前为null。

如果他们只使用SetSource(somestream)来使用SetSource(null)来释放资源,那么人们就会期待。不,他们认为“更好”,你必须使用Source = null代替释放资源而SetSource(null)抛出ArgumentNullException

这就是我所说的设计错误(打破了“最不期望”行为的规则,并导致只在运行时咬你的错误[除非有人制定了静态分析规则来捕捉这样的事情 - 当然需要元数据某些参数不能为空,如代码合同中所示))

我设法在前几天在ClipFlair Studio的AudioRecorder控件中重构一些代码时引入了这个bug: - (

请注意,您无法在MediaElement中使用类似Source = stream的内容来打开Stream,因为这是一个Uri属性(不是也接受Stream的Object属性),您必须使用{{3相反,所以你也希望能够使用SetSource(null)来释放资源。

更新:SetSource这在AudioRecorderView的AudioRecorderView类(使用MVVM模式)中,在Audio属性的“set”访问器中,它需要以下空值保护模式:

if (mediaStreamSource != null) 
  player.SetSource(mediaStreamSource); 
      //must set the source once, not every time we play the same audio, 
      //else with Mp3MediaSource it will throw DRM error 
else 
   player.Source = null; 

答案 2 :(得分:1)

mediaElement.Stop();
mediaElement.ClearValue(MediaElement.SourceProperty);

答案 3 :(得分:0)

我在显示图像方面遇到了类似的问题。在带有图像的控件中,每当用户尝试更新图像时,我都会收到“文件正在使用中”错误。解决方案是将BitmapImage.CacheOption属性设置为BitmapCacheOption.OnLoad

MSDN如果要关闭用于创建BitmapImage的流,请将CacheOption设置为BitmapCacheOption.OnLoad。默认的OnDemand缓存选项保留对流的访问,直到需要映像,并且清理由垃圾收集器处理。

在搜索了可用于MediaElement的类似属性后,结果发现没有一个属性。但是,根据MSDN上chacheoption for mediaelement帖子的回答, (长期啰嗦)实现这一目标的方式......来自相关答案:

  

我不确定您的MediaElement是否在UserControl中。但   无论如何,您可以将UserControl或Control设置为   IsEnabled = false,反过来会触发事件处理程序   IsEnabledChanged。在其中放置必要的代码来阻止   MediaElement从播放ME.Stop(),然后调用ME.Clear()和   ME.Source = null。之后你应该发现删除没有问题   源文件。

ME.Source = new Uri(MediaFilePath);
ME.Play();
...
private void DeleteButton_Click(object sender, RoutedEventArgs e) 
{ 
    ME.IsEnabled = false;   // This will call the Event Handler IsEnabledChanged 
    System.IO.File.Delete(MediaFilePath); 
    // Now after the player was stopped and cleared and source set to null, it 
    // won't object to deleting the file
}

private void ME_IsEnabledChanged(object sender, DependencyPropertyChangedEventArgs e)
{
    ME.Stop();
    ME.Clear();
    ME.Source = null;
}

我希望这会有所帮助。