C# 如何捕获外部异常

C# 如何捕获外部异常,c#,.net,dll,datagridview,vlc,C#,.net,Dll,Datagridview,Vlc,我正在使用nVLC dll在我的应用程序中使用VLC媒体播放器。除了一件事,它就像一个符咒。我有一个带有电影列表的DataGridView。当我从DataGridView中选择一部电影时,它开始在由nVLC处理的面板中播放该电影。我还使用过滤器过滤DataGridView中的电影。当我这样做几次时,我从nVLC DLL中得到一个错误: 发生CallbackOnCollectedDelegate 托管调试助手“CallbackOnCollectedDelegate”在“C:\Users\User\

我正在使用nVLC 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!vlceventhandlerelegate::Invoke'。 这可能会导致应用程序崩溃、损坏和数据丢失。什么时候 将委托传递给非托管代码时,必须通过 托管应用程序,直到保证它们永远不会 打电话来

问题是我听不懂那个解释。即使我对应用程序本身设置了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();
}
if(!string.IsNullOrEmpty(video\u url))
{
如果(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=新系统.Drawing.Point(pnlStartInfo.Location.X,(pnlStartInfo.Location.Y+(pnlStartInfo.Height-1));
pnlStartVideo.Name=“pnlStartVideo”;
pnlStartVideo.Size=新系统图纸尺寸(275153);
pnlStartVideo.TabIndex=3;
tpStart.Controls.Add(pnlStartVideo);
m_工厂=新MediaPlayerFactory(真);
m_player=m_factory.CreatePlayer();
m_player.WindowHandle=pnlStartVideo.Handle;
m_player.Events.PlayerStopped+=事件_PlayerStopped;
UISync ui=新的UISync();
ui.Init(this);
m_media=m_factory.CreateMedia(视频url);
m_播放器打开(m_媒体);
m_media.Parse(true);
m_media.Events.StateChanged+=事件_StateChanged;
m_player.Play();
}
托管调试助手“CallbackOnCollectedDelegate”

它不是可捕获的异常,因为它根本不是异常。托管调试助手是添加到调试器的帮助程序代码,可以在运行时检测各种故障。当它看到VLC播放器试图使用已处理的委托对象时,这一步就开始了。如果没有调试器,您的程序将崩溃并以更糟糕的方式消亡,这是一个AccessViolationException,也不可捕获,因为失败的是本机代码

查看VLC包装器源代码,必须只创建一次
m_player
实例,以避免此故障模式。当您像现在一样一次又一次地创建它时,以前的IDiskPlayer实例不再在任何地方引用。当本机VLC代码进行回调以触发事件时,垃圾收集器将收集它们。包装器也没有实现我所看到的正确清理,从而确保在释放对象时本机代码不再触发事件

强烈建议将
m_播放器
变量设置为静态。只分配一次


修复包装器需要编写InitializeEventEngine()的等效项,但需要将所有回调设置回null。这不一定是直截了当的,可能涉及到线程竞赛。依赖此代码是一种负担,您可能希望继续购物。

非常感谢。。听起来这应该行得通。今天晚些时候我将尝试这个方法,并将它标记为我的问题的答案。我花了很长时间才找到一个好的VLC包装器,但是运气不好,你知道有什么好的工作VLC包装器吗?嗯,没有,只有那些由程序员调试并将他们的更改贡献给开源项目的包装器才能相对无故障地工作。