2

非同期のOnMsgRecieved呼び出しで、コントロールに直接値を割り当てると、機能しません。その後、スレッドが安全でないことが原因であることがわかり、問題を解決するために次のコードを取得しました。今それは働いています。しかし、私はそれが実際に何をするのかわかりません。誰かが私にそれを完全に理解させることができますか?コードは次のとおりです。-

        public void listener_OnMsgRecieved(string aResponse)
    {
        ShowResponseMessage(aResponse);
    }

    public void ShowResponseMessage(string aResponse)
    {
        // InvokeRequired required compares the thread ID of the
        // calling thread to the thread ID of the creating thread.
        // If these threads are different, it returns true.
        if (this.listBox.InvokeRequired)
        {
            SetTextCallback d = new SetTextCallback(ShowResponseMessage);
            this.Invoke(d, new object[] { aResponse });
        }
        else
        {
            this.listBox.Items.Add(aResponse);
            label.Text = "Response received from Server :";
        }
    }
4

2 に答える 2

1

ShowResponseMessage が UI のスレッドとは別のスレッドで呼び出されると、InvokeRequiredが返され、Windows メッセージ キューにメッセージを送信するためにtrue使用されます。Control.Invoke

UI スレッドで実行される UI メッセージ ポンプは、メッセージをプルしてターゲット コントロールに配信します。ターゲット コントロールは、これがデリゲートの呼び出しを要求するメッセージであり、デリゲートがコントロールによって呼び出されることを確認します。 UI スレッドで実行されているため、クロススレッドの問題は解決されています。

秘訣は、非 UI 呼び出しスレッドでデリゲートが直接呼び出されないことです。Windows メッセージを使用すると、デリゲートを実行する命令が UI スレッドに渡され、メッセージに応答してデリゲートが実行されます。「Control.Invoke」は Windows[SendMessage][1]Control.BeginInvoke使用し、[PostMessage][2]Win32 API を使用してメッセージの受け渡しを容易にします。

于 2012-04-24T05:26:21.987 に答える
0

UI コントロールは、それが作成されたメイン スレッド/スレッド以外のスレッドから更新/変更することはできません。

あなたの場合、チェック InvokeRequired は、コントロールを変更したいスレッドが作成スレッドであるかどうかを確認し、そうでない場合はコールをメインスレッド/作成者に渡します。

「方法: Windows フォーム コントロールへのスレッド セーフな呼び出しを行う」を参照してください。

マルチスレッドを使用して Windows フォーム アプリケーションのパフォーマンスを向上させる場合は、スレッド セーフな方法でコントロールを呼び出す必要があります。

Windows フォーム コントロールへのアクセスは、本質的にスレッド セーフではありません。コントロールの状態を操作するスレッドが 2 つ以上ある場合、コントロールを強制的に矛盾した状態にすることができます。競合状態やデッドロックなど、その他のスレッド関連のバグが発生する可能性があります。コントロールへのアクセスがスレッドセーフな方法で実行されるようにすることが重要です。

Invoke メソッドを使用せずに、コントロールを作成したスレッド以外のスレッドからコントロールを呼び出すことは安全ではありません。

于 2012-04-24T05:25:47.590 に答える