内存泄漏在Windows IoT上播放视频UWP

时间:2017-04-26 08:28:55

标签: c# memory-leaks uwp windowsiot windows-iot-core-10

我已经构建了一个应用程序,可以从USB驱动器读取视频文件,并使用物理按钮在它们之间切换。该应用程序运行良好一段时间,但一段时间后,设备(DragonBoard 410c,最新的Windows Insider Preview Build 15051)崩溃,因为应用程序已消耗所有内存。

查看设备门户中的进程,每次切换视频文件时都会看到“工作集”内存跳转,而“私有工作集”大致保持不变(大约30MB)。

以下是我加载视频文件的方式:

C#

private IReadOnlyList<StorageFile> _videofiles

// list all available video files
public void Init(){
    var queryOptions = new QueryOptions();
    queryOptions.FolderDepth = depth;
    foreach (var fileType in fileTypes)
    {
        queryOptions.FileTypeFilter.Add(fileType);
    }

    var query = KnownFolders.RemovableDevices.CreateFileQueryWithOptions(queryOptions);
    _videofiles = await query.GetFilesAsync();
}

private async void SelectVideo(int videoId)
{         
    StorageFile videofile = _videofiles.Where(x => x.DisplayName == videoId.ToString()).FirstOrDefault();
    if (videofile != null)
    {
        Debug.WriteLine($"Video {videofile.DisplayName} was selected");
        var stream = await videofile.OpenAsync(FileAccessMode.Read);
        VideoPlayer.SetSource(stream, videofile.FileType);
    }
}

// since the button interrupt is not on the UI thread, SelectVideo() is called like this
private async void SelectVideoMarshalled(int videoId)
{
    await Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(CoreDispatcherPriority.Normal,
    () =>
    {
        SelectVideo(videoId);
    });
}

XAML

<ContentControl x:Name="VideoPlayer" Content="{x:Bind ViewModel.VideoPlayer, Mode=OneWay}"/>

我尝试在几个地方手动运行GC.Collect(),但还没有运气。有什么想法吗?

2 个答案:

答案 0 :(得分:1)

由于您有StorageFile个对象,我建议您使用Source属性和文件Path代替SetSource并手动打开Stream

此外,完成后应始终将MediaElement清空(最好在OnNavigatingFrom中完成)。

这是您的代码,简化:

private void SelectVideo(string videoId)
{
    var videofile = _videofiles.FirstOrDefault(x => x.DisplayName == videoId.ToString());
    if (videofile == null) return;

    Debug.WriteLine($"Video {videofile.DisplayName} was selected");

    VideoPlayer.Source = new Uri(videofile.Path);
}


protected override void OnNavigatedFrom(NavigationEventArgs e)
{
    VideoPlayer.Stop();
    VideoPlayer.Source = null;

    base.OnNavigatedFrom(e);
}

我也有一个侧面评论,你可以x:Bind到ViewModel的事件处理程序。

例如,如果您的视频文件列表是ListView字符串:

public void VideosListView_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
{
    if (e?.AddedItems?.Count > 0)
    {
        var fileDisplayName = e.AddedItems.FirstOrDefault() as string;
        if (!string.IsNullOrEmpty(fileDisplayName))
            SelectVideo(fileDisplayName);
    }
}

注意我只需要将方法签名更改为public,然后在XAML中就可以执行此操作:

<ListView ItemsSource="{x:Bind ViewModel.VideoFiles, Mode=OneTime}"
          SelectionChanged="{x:Bind ViewModel.VideosListView_OnSelectionChanged}"/>

无需编组回UI线程:)

最后,您可以查看the demo here on GitHub我已经实现了类似的内容。

答案 1 :(得分:1)

毕竟我的代码很好。我有几次Windows Update卡住/失败,我没有注意到。 当更新最终成功完成后,内存泄漏就消失了。