如何捕获外部异常

本文关键字:异常 外部 何捕获 | 更新日期: 2023-09-27 18:04:41

我正在使用VLC dll在我的应用程序中使用VLC媒体播放器。除了一件事,它就像一个咒语。我有一个带有电影列表的DataGridView。当我从DataGridView中选择一个电影时,它开始在由nVLC处理的面板内播放电影。我还使用过滤器来过滤DataGridView中的电影。当我这样做了几次,我得到一个错误从nVLC DLL:

CallbackOnCollectedDelegate发生

管理调试助手'CallbackOnCollectedDelegate'在'C:'Users'User'Documents'Visual Studio 2013'Projects'Soft.UltimateMovieManager'Soft.UltimateMovieManager'bin'Release'Soft.UltimateMovieManager.vshost.exe'.

附加信息:对垃圾收集进行了回调类型委托"nVLC.Implementation ! Implementation.VlcEventHandlerDelegate::调用"。这可能会导致应用程序崩溃、损坏和数据丢失。当将委托传递给非托管代码时,它们必须由托管应用程序,直到保证它们永远不会被托管调用。

问题是我抓不到那个异常。即使我在应用程序上设置了try/catch,它仍然不能被处理。

这是我可以自己解决的问题,还是我使用的nVLC dll的问题?

if (!string.IsNullOrEmpty(video_url))
{
    if (pnlStartVideo != null)
    {
        pnlStartVideo.Dispose();
    }
    pnlStartVideo = new System.Windows.Forms.Panel();
    pnlStartVideo.Anchor = ((System.Windows.Forms.AnchorStyles)((System.Windows.Forms.AnchorStyles.Bottom | System.Windows.Forms.AnchorStyles.Right)));
    pnlStartVideo.BackgroundImageLayout = System.Windows.Forms.ImageLayout.Center;
    pnlStartVideo.BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle;
    pnlStartVideo.Location = new System.Drawing.Point(pnlStartInfo.Location.X, (pnlStartInfo.Location.Y + (pnlStartInfo.Height - 1)));
    pnlStartVideo.Name = "pnlStartVideo";
    pnlStartVideo.Size = new System.Drawing.Size(275, 153);
    pnlStartVideo.TabIndex = 3;
    tpStart.Controls.Add(pnlStartVideo);
    m_factory = new MediaPlayerFactory(true);
    m_player = m_factory.CreatePlayer<IDiskPlayer>();
    m_player.WindowHandle = pnlStartVideo.Handle;
    m_player.Events.PlayerStopped += Events_PlayerStopped;
    UISync ui = new UISync();
    ui.Init(this);
    m_media = m_factory.CreateMedia<IMedia>(video_url);
    m_player.Open(m_media);
    m_media.Parse(true);
    m_media.Events.StateChanged += Events_StateChanged;
    m_player.Play();
}

如何捕获外部异常

托管调试助手'CallbackOnCollectedDelegate'…

它不是一个可捕获的异常,因为它根本不是一个异常。托管调试助手是添加到调试器中的帮助代码,可以在运行时检测各种故障。当它看到VLC播放器试图使用一个处置委托对象时,它就会介入。如果没有调试器,你的程序会崩溃,并以更糟糕的方式死亡,一个AccessViolationException,也无法捕获,因为它是本机代码失败。

查看VLC包装器源代码,必须只创建一次 m_player实例以避免这种失败模式。当您像现在一样一遍又一遍地创建它时,以前的iddiskplayer实例在任何地方都不再被引用。垃圾收集器将收集它们,当本地VLC代码进行回调以触发事件时,会发生大爆炸。包装器也没有实现我所看到的适当的清理,确保在对象被处置时本机代码不能再触发事件。

强烈建议将m_player变量设置为static。只分配一次。

修复包装器将需要编写相当于initializeEventsEngine()的代码,但将所有回调函数设置为空。这并不一定是直截了当的,可能会涉及到线程竞争。依赖于这段代码是一种负担,您可能想继续购买。