Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/319.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 让GCHandle.Alloc()固定窗体以便本机代码可以使用句柄时出现问题 我有一个CE.0R3系统,使用.NETCF3.5,并使用P/PoCKE来接口几个本地C++ DLL。_C#_Compact Framework - Fatal编程技术网

C# 让GCHandle.Alloc()固定窗体以便本机代码可以使用句柄时出现问题 我有一个CE.0R3系统,使用.NETCF3.5,并使用P/PoCKE来接口几个本地C++ DLL。

C# 让GCHandle.Alloc()固定窗体以便本机代码可以使用句柄时出现问题 我有一个CE.0R3系统,使用.NETCF3.5,并使用P/PoCKE来接口几个本地C++ DLL。,c#,compact-framework,C#,Compact Framework,这些设备偶尔会崩溃,有时我们会看到一个弹出窗口,上面写着“应用程序myc#app.exe遇到严重错误,必须关闭” 我们所做的一件事是把一个C语言形式的句柄传递给一个C++应用程序,它使用DirectShow来呈现C形式的视频。 我一直在研究它,发现了一些关于使用GCHandle固定托管对象以使其不移动的讨论 我添加了诊断来尝试检测这是否是问题所在,还添加了GCHandle.Alloc()来锁定对象。出于某种原因,对象似乎在内存中移动,即使它们应该被固定 以下是我代码的一部分: Diag.Putl

这些设备偶尔会崩溃,有时我们会看到一个弹出窗口,上面写着“应用程序myc#app.exe遇到严重错误,必须关闭”

我们所做的一件事是把一个C语言形式的句柄传递给一个C++应用程序,它使用DirectShow来呈现C形式的视频。 我一直在研究它,发现了一些关于使用GCHandle固定托管对象以使其不移动的讨论

我添加了诊断来尝试检测这是否是问题所在,还添加了GCHandle.Alloc()来锁定对象。出于某种原因,对象似乎在内存中移动,即使它们应该被固定

以下是我代码的一部分:

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)

为什么即使把手被固定,它也会发生变化?

您误解了GCHandle的工作原理和使用方式

首先,GCHandle只能用于blittable类型,所以不能固定表单本身。您所做的是固定句柄,这基本上是在代码中对GC说“不要移动内存中有窗体地址的位置”。这意味着句柄本身的存储位置不能移动。没有任何东西可以阻止窗体移动,从而阻止句柄保持的值

句柄正在更改有点奇怪,我怀疑一旦创建了表单本身,本机表单句柄本身就不能更改。这让我觉得你有一个伪句柄。如果是这样的话,在本机调用中使用它应该是行不通的

我并不确信错误是一种运动,因为我以前从未见过这种行为——我更倾向于认为这是试图使用已处理表单的句柄,但您已经在进行调试,并且可能对它有更好的感觉

无论如何,如果您确实认为失败是由于句柄更改引起的,那么最好的解决方法是使用p/Invoke(到CreateWindowEx)来创建容器表单本身。GC无法移动它,因为它对它一无所知。这将消除作为罪魁祸首的压缩(或解决问题)