0

.NetCF3.5 を使用し、P/Invoke を使用していくつかのネイティブ C++ dll をインターフェイスする CE6.0R3 システムがあります。

これらのデバイスは時折クラッシュし、「アプリケーション myc#app.exe で重大なエラーが発生したため、シャットダウンする必要があります」というポップアップが表示されることがあります。

私たちが行うことの 1 つは、C# フォームへのハンドルを、DirectShow を使用して C# フォームでビデオをレンダリングするネイティブ 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)

ピン留めしているのにハンドルが変わるのはなぜですか?

4

1 に答える 1

2

GCHandle の仕組みと使用方法を誤解しています。

まず、GCHandle は blittable 型でのみ使用できるため、フォーム自体を固定することはできません。あなたがしているのはハンドルを固定することです。これは基本的に、コード内の GC に「メモリ内のフォームのアドレスがある場所を移動しないでください」と言っています。つまり、ハンドル自体の保管場所は移動できません。フォームの移動を妨げるものは何もないため、ハンドルが保持する値が保持されます。

ハンドルが変更されるのは少し奇妙です。フォーム自体が作成されると、ネイティブ フォーム ハンドル自体は変更できないのではないかと思います。それはあなたが疑似ハンドルを持っていると私に思わせます。その場合、ネイティブ呼び出しで使用することはできません。

私はこれまでそのような動作を見たことがなかったので、エラーが動きであると固く確信していません.Disposed Formのハンドルを使用しようとしていると思いがちですが、あなたはデバッグを行っており、より良い感触を得られる可能性があります。

いずれにせよ、失敗の原因がハンドルの変更であると本当に信じている場合、最善の回避策は、(CreateWindowEx に対して) P/Invoke を使用してコンテナー Form 自体を作成することです。GC はそれについて何も知らないため、移動できません。これにより、犯人としての圧縮が排除されます(または問題が修正されます)。

于 2013-05-09T23:35:17.283 に答える