我有一个 CE6.0R3 系统,它使用 .NetCF3.5 并使用 P/Invoke 来连接几个本机 C++ dll。
这些设备偶尔会崩溃,有时我们会看到一个弹出窗口,上面写着“应用程序 myc#app.exe 遇到严重错误,必须关闭”。
我们所做的其中一件事是将 C# 表单的句柄传递给本地 C++ 应用程序,该应用程序使用 DirectShow 在 C# 表单上呈现视频。
我一直在研究它,并发现了一些关于使用 GCHandle 固定托管对象以使其不会移动的讨论。
我添加了诊断程序来尝试检测这是否是问题,并添加了 GCHandle.Alloc()s 来固定对象。出于某种原因,对象似乎在内存中移动,即使它们应该被固定。
这是我的代码的一部分:
Diag.Putline("_videoplay create");
_videoplay = new Form();
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before pinning Handle");
GCHandle gch = GCHandle.Alloc(_videoplay.Handle, GCHandleType.Pinned);
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before pinning Form");
GCHandle gch_videoplay = GCHandle.Alloc(_videoplay, GCHandleType.Pinned); // Pin the _videoplay object instance so it won't get moved by GC
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " after pinning");
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .Location");
_videoplay.Location = new Point(x, y);
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .Size");
_videoplay.Size = new Size(w, h);
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .BackColor");
_videoplay.BackColor = bgColor;
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .FormBorderStyle");
_videoplay.FormBorderStyle = FormBorderStyle.None;
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .Owner");
_videoplay.Owner = _mediaform;
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before .Show()");
_videoplay.Show();
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " after .Show()");
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " before directshow_connect");
Diag.Putline("directshow_connect");
// P/Invoke to our native C++ application based on this code: http://msdn.microsoft.com/en-us/library/ms899491.aspx
// Pass the handle ot our form that we want to display the video on
// the directshow HWND will be a WS_CHILD of _videoplay
directshow_connect(_videoplay.Handle);
Diag.Putline("_videoplay.Handle = " + _videoplay.Handle + " after directshow_connect");
和输出:
14:59:37| _videoplay create
14:59:37| _videoplay.Handle = 1879191552 before pinning Handle
14:59:37| _videoplay.Handle = 1879191552 before pinning Form
14:59:37| _videoplay.Handle = 1879191552 after pinning
14:59:37| _videoplay.Handle = 1879191552 before .Location
14:59:37| _videoplay.Handle = 1879191552 before .Size
14:59:37| _videoplay.Handle = 1879191552 before .BackColor
14:59:37| _videoplay.Handle = 1879191552 before .FormBorderStyle
14:59:37| _videoplay.Handle = 1879191776 before .Owner
14:59:37| _videoplay.Handle = 1879192000 before .Show()
14:59:37| _videoplay.Handle = 1879192000 after .Show()
14:59:37| _videoplay.Handle = 1879192000 before directshow_connect
14:59:37| directshow_connect
14:59:39| _videoplay.Handle = 1879192000 after directshow_connect
14:59:41| _videoplay.Handle = 1879193248 (_TickTockThreadProc)
14:59:41| _videoplay.Handle = 1879193248 (_TickTockThreadProc)
14:59:41| _videoplay.Handle = 1879193248 (UpdateTimer_Tick)
14:59:41| _videoplay.Handle = 1879193248 (UpdateTimer_Tick)
14:59:41| _videoplay.Handle = 1879193248 (_TickTockThreadProc)
14:59:42| _videoplay.Handle = 1879193248 (_TickTockThreadProc)
为什么手柄即使被固定也会改变?