Uwp MediaPlayerElement - How to release video file played from NAS to avoid "..being used by another process." error for the next update job?

SmilingMoon 981 Reputation points
2021-03-28T00:09:16.687+00:00

Hello,
In UWP app, I want to play video and update the video file's property (Tags).
The following code works well for the C:\ local video file.
But, it throws error for video file from NAS (Network drive, I use synology): \MyNAS\video\Test\20201125_032706.mp4

MainPage.xaml

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <StackPanel Orientation="Horizontal" Grid.Row="0">
            <Button Content="Open" Click="OpenButton_Click"></Button>
            <Button Content="Close and Update" Click="CloseUpdateButton_Click"></Button>
        </StackPanel>
        <MediaPlayerElement x:Name="mpPlayer"                    
                    AutoPlay="False" 
                    AreTransportControlsEnabled="True"
                    Grid.Row="1"        
                            Stretch="Uniform"
                            HorizontalAlignment="Stretch"
                            VerticalAlignment="Stretch"
                            >
        </MediaPlayerElement>
    </Grid>


    public sealed partial class MainPage : Page
    {
        public MainPage()
        {
            this.InitializeComponent();

            mpPlayer.MediaPlayer.MediaEnded += MediaPlayer_MediaEnded;
            mpPlayer.MediaPlayer.MediaOpened += MediaPlayer_MediaOpened;
            mpPlayer.MediaPlayer.CurrentStateChanged += MediaPlayer_CurrentStateChanged;
        }
        async void Log(string msg)
        {
            System.Diagnostics.Debug.WriteLine(msg);
        }
        async private void MediaPlayer_CurrentStateChanged(Windows.Media.Playback.MediaPlayer sender, object args)
        {
             Log($"\n{DateTime.Now} - Media StateChanged - {sender.PlaybackSession.PlaybackState.ToString()}");
            //=> Only paused called twice when closed.
        }

        async private void MediaPlayer_MediaOpened(Windows.Media.Playback.MediaPlayer sender, object args)
        {
            Log($"\n{DateTime.Now} - Media Opened");
        }

        async private void MediaPlayer_MediaEnded(Windows.Media.Playback.MediaPlayer sender, object args)
        {
            Log($"\n{DateTime.Now} - Media Ended");
        }

        StorageFile file;
        async private void OpenButton_Click(object sender, RoutedEventArgs e)
        {
            var picker = new Windows.Storage.Pickers.FileOpenPicker();
            picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;
            picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;
            picker.FileTypeFilter.Add(".mp4");
            file = await picker.PickSingleFileAsync();
            if (file != null)
            {
                // Application now has read/write access to the picked file
                mpPlayer.Source = MediaSource.CreateFromStorageFile(file);
                mpPlayer.MediaPlayer.Play();
            }
        }

        async private void CloseUpdateButton_Click(object sender, RoutedEventArgs e)
        {
            try
            {
                mpPlayer.MediaPlayer.Pause();
                mpPlayer.MediaPlayer.Source = null;
                //mpPlayer.Source = EmptyVideo; //Sometimes work.
                await Task.Delay(500);

                VideoProperties vdPt = await file.Properties.GetVideoPropertiesAsync();

                string[] keywords = new string[] { "Test", "Video", "Tags", "Update" };
                vdPt.Keywords.Clear();
                foreach (var tag in keywords) //Tags
                {
                    vdPt.Keywords.Add(tag);
                }
                await vdPt.SavePropertiesAsync();
            }
            catch (Exception ex)
            {
                Log($"\n{DateTime.Now}\n {ex.Message}");
            }
        }
    }

The code works well if I copy the video file into local drive (under C:\Temp) and tested. But it doesn't work from the video file from NAS drive, such as my Synology network drive over home wifi, \MyNAS\video\Test\20201125_032706.mp4.
And, it throws error:
"3/27/2021 4:52:35 PM - Media StateChanged - None
Exception thrown: 'System.IO.FileLoadException' in System.Private.CoreLib.dll
3/27/2021 4:52:36 PM
The process cannot access the file because it is being used by another process. (Exception from HRESULT: 0x80070020)"

Try to force to release the file played, I put extra code
await Task.Delay(500), but it doesn't work. Even I put 10 seconds or 1 minutes, it doesn't work well.

Also, I try to bind emptyVideo to release previous video, it sometimes work, but not always. Mostly no.

  1. Is there a way to force to release the video file from NAS?
  2. If NOT, is there a way to know or get notified via event when the file is released?
  3. If 1 and 2 is not possible, is there a way to check if the file is being used by another process programmatically?

Or, am I using wrong control? Or, is the code opening video is wrong?

Any comment helps,
Thank you!

Universal Windows Platform (UWP)
0 comments No comments
{count} votes

Accepted answer
  1. Nico Zhu (Shanghai Wicresoft Co,.Ltd.) 12,856 Reputation points
    2021-03-29T06:14:52.29+00:00

    Hello, Welcome to Micorosoft Q&A,

    How to release video file played from NAS to avoid "..being used by another process."

    The problem is looks , the file has not been released by previous media, For this scenario, we suggest your call Dispose to release MediaSourece manually.

     private MediaSource _mediaSourece;  
     async private void OpenButton_Click(object sender, RoutedEventArgs e)  
     {  
         var picker = new Windows.Storage.Pickers.FileOpenPicker();  
         picker.ViewMode = Windows.Storage.Pickers.PickerViewMode.Thumbnail;  
         picker.SuggestedStartLocation = Windows.Storage.Pickers.PickerLocationId.PicturesLibrary;  
         picker.FileTypeFilter.Add(".mp4");  
         file = await picker.PickSingleFileAsync();  
         if (file != null)  
         {  
             // Application now has read/write access to the picked file  
      
             _mediaSourece = MediaSource.CreateFromStorageFile(file);  
             mpPlayer.Source = _mediaSourece;  
             mpPlayer.MediaPlayer.Play();  
         }  
     }  
      
     async private void CloseUpdateButton_Click(object sender, RoutedEventArgs e)  
     {  
         try  
         {  
             mpPlayer.MediaPlayer.Pause();                     
             mpPlayer.MediaPlayer.Source = null;  
             _mediaSourece.Dispose();  
         }  
    }  
    

    If the response is helpful, please click "Accept Answer" and upvote it.
    Note: Please follow the steps in our documentation to enable e-mail notifications if you want to receive the related email notification for this thread.


0 additional answers

Sort by: Most helpful