强制 MediaElement 在播放后释放流

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

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

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

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

我面临的问题是当我使用媒体元素播放录制的音频时。流被锁定到媒体元素。我无法覆盖该文件,甚至无法再次播放它,因为

SetSource()
方法会抛出异常。

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

c# wpf audio windows-phone-8 wpf-controls
4个回答
11
投票

基于@Sheridan 的回答,我想出的方法是有效的。

每当使用

MediaElement
功能停止
Stop()
时,将
Source
属性设置为
null
,如下所示:

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

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


2
投票
mediaElement.Stop();
mediaElement.ClearValue(MediaElement.SourceProperty);

2
投票

如果您使用 MediaElement,请确保您不会被这个咬住:
MediaElement.SetSource方法

ArgumentNullException - mediaStreamSource 为 null。
...

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

如果 MediaElement 从 UI 树中删除,而它有一个打开的 MediaStreamSource,后续对 SetSource 的调用可能会被忽略。到 确保 featureSetSource 调用有效,将 Source 属性设置为 从 UI 树中分离 MediaElement 之前为 null。

人们自然会期望,如果他们只使用 SetSource(somestream) 来使用 SetSource(null) 来释放资源。不,他们认为“更好”,你必须使用 Source=null 来释放资源,并且 SetSource(null) 抛出 ArgumentNullException

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

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

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

更新:已修复 AudioRecorderControl 的 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; 

0
投票

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

BitmapImage.CacheOption
属性设置为
BitmapCacheOption.OnLoad
:

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

在搜索了可用于您的

MediaElement
的类似属性后,结果发现没有。然而,根据 MSDN 的 chacheoption for mediaelement 帖子的答案,有 is 一种(冗长的)方法可以实现这一点......来自相关答案:

我不确定您的 MediaElement 是否在 UserControl 中。但 无论哪种情况,您都可以将 UserControl 或 Control 设置为 IsEnabled=false,这又会触发事件处理程序 已启用已更改。在其中放置必要的代码来停止 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;
}

我希望这有帮助。

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