WndProcがメインUIスレッドではなく別のスレッドで呼び出されることを想像しました。
私は正しかったので、フォームでInvokeRequiredとInvokeを使用するだけで、UIスレッドにメッセージボックスを表示するのに十分だと思いました。
私は間違っていた。そして、その理由がわかりません。
この問題を回避するにはどうすればよいですか?Googleを調べましたが、解決策が見つかりませんでした。
私がやろうとしているのは、クリップボードが変更されたときにカスタムイベント(ClipboardUpdate)を発生させることです。
メッセージボックスは単なるテストでしたが、機能しませんでした。文字列(フォームのプライベートフィールド)のようなものを変更するだけで機能しますが、安全でない方法でのクロススレッド操作であるため、この動作は適切ではありません。
アップデート1:
友人のコンピューターで作成したのでここにはコードがありませんが、短いので自分が書いたものを正確に説明できます。Visual Studioを使用して、何も使用せずに基本的なWinFormを作成しました。AddClipboardFormatListener(相互運用機能ですが、関数としては非常に簡単です。intを返し、IntPtrを受け入れる)関数(Windows 7 OSの場合)を使用して、winproc内のWM_CLIPBOARDUPDATEメッセージを検出しました(単純なif、* if(e.Msg == ClipboardExtension .WM_CLIPBOARDUPDATE)DoClipboardUpdate(); *)。
DoClipboardUpdateはこれを行います:
if (InvokeRequired)
Invoke(new VoidDelegate(OnClipboardUpdate));//Void delegate it's a delegate that doesn't take
// Params and returns void
else
OnClipboardUpdate();
とても簡単ですよね?OnClipboardUpdateはこれを行うだけです:
if (ClipboardUpdate != null) ClipboardUpdate(null,EventArgs.Empty);
ClipboardUpdateは、次のように宣言されたイベントです。
public event EventHandler<EventArgs> ClipboardUpdate;
結局、ClipboardUpdateイベントにサブスクライブされた唯一のメソッドには、次のものが含まれています。
MessageBox.Show("test");
コードを実行するとどうなりますか?イベントがトリガーされ(例外を試してみましたが、機能します)、メッセージボックスはポップアップしませんが、ポップアップが開いたように動作するため、フォームを操作できなくなります(これは「通常の」動作です。別のスレッドでポップアップを開くので、そう言ったのです)。
これを解決する方法について何か提案はありますか?