'MediaElement.SetSource()' 更新不一致

'MediaElement.SetSource()' isn't updating consistently

我的程序应该在用户按下 'Play' 按钮时播放视频。虽然它通常会这样做,但他们第一次按下 'Play' 按钮时什么也不会发生。

我已将此错误追溯到以下代码,它设置了我的 MediaElement 'VideoPlayer':

public void playVideo_Tapped(object sender, TappedRoutedEventArgs e)
{
  setUpVideo();
  VideoPlayer.Play();
}

public async void setUpVideo()
{
  if(vm == null) return;
  StorageFile videoFile = vm.videoFile;

  if (videoFile == null || !videoFile.ContentType.Equals("video/mp4")) return;

    using (IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read))
    {
      VideoPlayer.SetSource(fileStream, videoFile.ContentType);
    }
}

罪魁祸首似乎是最后的 'SetSource()' 方法。从第一次单击 'Play' 到下一次单击唯一变化的变量是变量 'VideoPlayer.PlayToSource',它从 null 更改为实际值。

(作为旁注,变量 'VideoPlayer.CurrentState' 也从 'Closed' 更改为 'Opening' 但在第二次单击之前将自身重置为 'Closed'。只有 'PlayToSource' 改变了功能。)

我认为我可以通过在第一种方法中执行此操作来快速修复:

  setUpVideo();
  setUpVideo();
  VideoPlayer.Play();

不是很好的代码,但它应该把事情弄清楚,对吧?没有!这会导致 NullReferenceException。在第二次调用 'setUpVideo()' 时,我发现 'PlayToSource' 仍然有一个值并且 'VideoPlayer.CurrentState' 仍然设置为 'Opening'... 以某种方式触发了 NullReferenceException。

我希望解决方案是以下之一:

1.) 在调用 'SetSource' 之前在第一次点击时设置 'VideoPlayer.PlayToSource'。

2.) 在快速修复中,在两次调用之间将 'VideoPlayer.CurrentState' 设置回 'Closed'。

3.) 模仿第一次点击的其他一些东西。

当然,我的两个想法都涉及更改只读变量。这就是我被困的地方。我将包括 .xaml 代码以备不时之需,但我相信方法 'SetSource' 是我的麻烦的根源:

<Grid x:Name="VideoViewerParentGrid" Background="DarkGreen" Height="{Binding VideoViewerParentGridHeight }" Width="{Binding VideoViewerParentGridWidth}">
    <MediaElement x:Name="VideoPlayer" HorizontalAlignment="Center" VerticalAlignment="Bottom" Stretch="Uniform"
                  Visibility="{Binding VideoVisibility, Converter={StaticResource visibilityConverter}}"/>
    <Button Style="{StaticResource BackButtonStyle}" Tapped="VideoViewerClose_Tapped" HorizontalAlignment="Left" VerticalAlignment="Top"/>
    <Button Name="Play_Button" Content="Play Video" FontSize="26" Tapped="playVideo_Tapped"
            VerticalAlignment="Top" HorizontalAlignment="Left" Height="60" Width="180" Margin="0,80,0,0"/>
</Grid>

----更新----

一些更多的调查表明,在第一次点击时 'VideoPlayer.CurrentState' 永远不会达到 'Playing' 状态,而是从 'Opening' 直接回到 'Closed'。只要程序是 运行,它就不会对任何后续点击执行此操作。仍在调查此问题的原因。

您缺少 "await" 关键字。这样做:-

await setUpVideo();

简短版本,此问题已通过更改以下内容得到解决:

using (IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read))
{
  VideoPlayer.SetSource(fileStream, videoFile.ContentType);
}

...成为这样的:

IRandomAccessStream fileStream = await videoFile.OpenAsync(FileAccessMode.Read);
VideoPlayer.SetSource(fileStream, videoFile.ContentType);

更长的版本,我的代码因错误 "mf_media_engine_err_src_not_supported hresult - 0xc00d36c4" 而失败,该错误正在关闭我的 MediaElement 而不是播放它。发生这种情况是因为当我离开 'using' 代码块时,'IRandomAccessStream' 会在我读取文件的过程中关闭。我不是 100% 清楚为什么它会在第一个 运行 代码之后完成整个过程,但至少它现在可以可靠地工作。

我还必须在应得的地方给予表扬,我在这里找到了这个答案:Windows 8 app - MediaElement not playing ".wmv" files