ZeBobo5 / Vlc.DotNet

.NET control that hosts the audio/video capabilities of the VLC libraries
MIT License
948 stars 416 forks source link

Crashes after dispose #622

Open mazurekj opened 4 years ago

mazurekj commented 4 years ago

I have an issue about Vlc.DotNet.

Generic information

Summary

System.AggregateException: Wyjątków zadania nie zaobserwowano ani przez oczekiwanie na zadanie, ani przez uzyskanie dostępu do jego właściwości Exception. W wyniku tego niezaobserwowany wyjątek został wywołany ponownie przez wątek finalizatora. ---> System.NullReferenceException: Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu. w Vlc.DotNet.Core.VlcMediaPlayer.<>cDisplayClass167_1.b0() w System.Threading.Tasks.Task.Execute() --- Koniec śladu stosu wyjątków wewnętrznych --- ---> (Wyjątek wewnętrzny #0) System.NullReferenceException: Odwołanie do obiektu nie zostało ustawione na wystąpienie obiektu. w Vlc.DotNet.Core.VlcMediaPlayer.<>cDisplayClass167_1.b0() w System.Threading.Tasks.Task.Execute()<---

This exception comes out randomly, after disposing.

We initialize the control this way: player.SourceProvider.CreatePlayer(player.VlcLibDirectory,ParseParameters(player.ViewModel.Parameters)); player.SourceProvider.MediaPlayer.Log += MediaPlayerOnLog; player.SourceProvider.MediaPlayer.Playing += MediaPlayerOnPlaying; player.SourceProvider.MediaPlayer.EncounteredError += MediaPlayerOnEncounteredError; player.SourceProvider.MediaPlayer.EndReached += MediaPlayerOnEndReached; player.SourceProvider.MediaPlayer.Play(player.ViewModel.StreamUrl);

And it is disposed this way: `if (player.SourceProvider.MediaPlayer == null) { return; }

player.SourceProvider.MediaPlayer.Log -= MediaPlayerOnLog; player.SourceProvider.MediaPlayer.Playing -= MediaPlayerOnPlaying; player.SourceProvider.MediaPlayer.EncounteredError -= MediaPlayerOnEncounteredError; player.SourceProvider.MediaPlayer.EndReached -= MediaPlayerOnEndReached;

player.SourceProvider.Dispose();`

jeremyVignelles commented 4 years ago

Can you send a minimal repro on github so that I can try it locally?

mazurekj commented 4 years ago

Ok. After some changes in your code (VlcMediaPlayer.Events.Log.cs)

private void OnLogInternal(IntPtr data, VlcLogLevel level, IntPtr ctx, string format, IntPtr args)
        {
            if (disposed)
            {
                return;
            }
            if (this.log != null)
            {
                // Original source for va_list handling: https://stackoverflow.com/a/37629480/2663813
                var byteLength = Win32Interops._vscprintf(format, args) + 1;
                var utf8Buffer = Marshal.AllocHGlobal(byteLength);

                string formattedDecodedMessage;
                try
                {
                    Win32Interops.vsprintf(utf8Buffer, format, args);

                    formattedDecodedMessage = Utf8InteropStringConverter.Utf8InteropToString(utf8Buffer);
                }
                finally
                {
                    Marshal.FreeHGlobal(utf8Buffer);
                }

                string module;
                string file;
                uint? line;
                if (Manager == null)
                {
                    return;
                }
                this.Manager.GetLogContext(ctx, out module, out file, out line);

                // Do the notification on another thread, so that VLC is not interrupted by the logging
#if NETSTANDARD1_3 || NETSTANDARD2_0 || NET45
                Task.Run(() => {
                    if (disposed)
                    {
                        return;
                    }

                   this.log?.Invoke(this.myMediaPlayerInstance, new VlcMediaPlayerLogEventArgs(level, formattedDecodedMessage, module, file, line));
                });
#else
                ThreadPool.QueueUserWorkItem(eventArgs =>
                {
                    if (disposed)
                    {
                        return;
                    }
                    this.log?.Invoke(this.myMediaPlayerInstance, (VlcMediaPlayerLogEventArgs)eventArgs);
                }, new VlcMediaPlayerLogEventArgs(level, formattedDecodedMessage, module, file, line));
#endif
            }

It is now working. But now I am experiencing the issue: https://github.com/ZeBobo5/Vlc.DotNet/issues/625

only in cases when I try to dispose MediaPlayer and it is not rendering because of the slow speed of IP camera stream, but the player says - it is Playing.