2017-04-26 8 views
1

私は、USBドライブからビデオファイルを読み込んで、物理的なボタンを使ってビデオファイルを切り替えることのできるアプリケーションを構築しました。アプリケーションはしばらくはうまくいくが、しばらくすると、すべてのメモリがアプリケーションによって消費されたため、デバイス(DragonBoard 410c、最新のWindows Insider Preview Build 15051)がクラッシュする。Windows IoTでメモリリークを再生する| UWP

デバイスポータルのプロセスを見ると、ビデオファイルを切り替えるたびに「ワーキングセット」メモリがジャンプするのがわかります。「プライベートワーキングセット」はほぼ同じままです(約30MB)。私はいくつかの場所で手動)(GC.Collectを実行しようとしたませんが、まだ運き

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}"/> 

:ここ

は、私はビデオファイルをロードする方法を説明します。何か案は?

+0

すべてのストリームは使い捨てですので、 'SelectVideo'メソッドでストリームの新しいインスタンスに設定した後、' VideoPlayer'のソースとして設定した前のストリームを破棄する必要があります。 –

+0

ストリームの呼び出し.Dispose(); VideoPlayer.SetSource()の直後(これはメモリのスパイクが発生する場所です)は役に立ちません。 – Thomas

+0

別のページに移動してもメモリを解放するのに役立たない – Thomas

答えて

1

結局のところ、コードはうまくいきました。私は気づいていなかったWindows Updateが何度も立ち往生/失敗した。 更新プログラムが正常に完了すると、メモリリークはなくなりました。

1

あなたがStorageFileオブジェクトを持っているので、私はSourceプロパティを使用して、ファイルのPath代わりSetSourceのと手動Streamを開くことをお勧めします。

また、完了したらMediaElementを常に無効にする必要があります(OnNavigatingFromで実行するのが最適です)。ここで

簡略化され、あなたのコードです:私はまた、あなたがのViewModelにx:Bindイベントハンドラをすることができ、サイドのコメントを持っている

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

たとえば、ビデオファイルのリストは、文字列のListViewある場合:

<ListView ItemsSource="{x:Bind ViewModel.VideoFiles, Mode=OneTime}" 
      SelectionChanged="{x:Bind ViewModel.VideosListView_OnSelectionChanged}"/> 
:私だけ publicにメソッドシグネチャを変更するには、その後、XAMLでこれを行うことができます必要

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

お知らせあなたは私がSOMETを実装しましたthe demo here on GitHubをチェックアウトすることができます

バックUIスレッドにマーシャリングする必要はありません:)

最後に、これに類似したヒンジ。

+0

詳細な回答ありがとうございます。問題は実際にはWindows Updateが不足していることに由来していますが、それを行う方法を確認することはまだ素晴らしいですし、これらのベストプラクティスを自分のコードに含めることを試みます。 – Thomas

関連する問題