【问题标题】:Forcing MediaElement to Release Stream after playback播放后强制 MediaElement 释放流
【发布时间】:2013-10-10 11:14:31
【问题描述】:

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

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

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

我面临的问题是,当我使用媒体元素播放录制的音频时。 Stream 被锁定到媒体元素。由于SetSource() 方法会引发异常,因此我无法覆盖该文件,甚至无法再次播放它。

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

【问题讨论】:

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


    【解决方案1】:

    根据@Sheridan 的回答,我想出的就是这个。

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

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

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

    【讨论】:

      【解决方案2】:

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

      ArgumentNullException - mediaStreamSource 为空。
      ...

      调用此方法后,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) 来释放资源。

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

      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; 
      

      【讨论】:

        【解决方案3】:
        mediaElement.Stop();
        mediaElement.ClearValue(MediaElement.SourceProperty);
        

        【讨论】:

          【解决方案4】:

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

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

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

          我不确定您的 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;
          }
          

          我希望这会有所帮助。

          【讨论】:

          • 媒体元素上没有“IsEnabled”属性。尽管您将源属性设置为 null 的建议有效。还要感谢有关 BitmapImage 的信息,它将在我的应用程序的另一个场景中对我有所帮助。
          • 我担心 youIsEnabled 属性有误,MSDN 上的 MediaElement Properties 页面会同意我的看法,但我很高兴这已修复你的问题。
          • 我不知道其他平台上的 MediaElement,但在 Windows Phone 8 上没有“IsEnabled”属性。它显示在 MSDN 上,但如果您签入 Visual Studio,它就不存在了。
          • 抱歉,我没有注意到那个标签。很高兴你对它进行了排序。
          猜你喜欢
          • 2020-03-22
          • 1970-01-01
          • 1970-01-01
          • 2012-07-20
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2018-09-02
          • 1970-01-01
          相关资源
          最近更新 更多