4

私のプログラムの一部は、シリアルポートの受信データにイベントハンドラーを使用しています。データを受信すると、受信したテキストがテキストボックス(rx)に追加されるという考え方です。以前はこの問題を抱えていませんでしたが、何かが変わって何がわからないのです。だから今、私はこれが処理される方法を再検討しています。

私のwinformのフォームロード中に、私が最後に行うことは

if (!serialPort1.IsOpen)
{
     serialPort1.Open();
     serialPort1.DataReceived += new SerialDataReceivedEventHandler(DataReceivedHandler);
}

次に、イベントハンドラーがあります

private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e)
{
     string indata1 = serialPort1.ReadExisting();
    // rx.Text = " "; accidentally posted this. it was from trial and error.  
     rx.AppendText(Environment.NewLine + indata1);
}

プログラムを実行すると、で停止しrx.AppendText(Environment.NewLine + indata1);、エラーが発生します

invalidoperationexceptionは処理されませんでした:コントロールは、作成されたスレッド以外のスレッドからアクセスされました。

私が読むことができたものから、私はinvokeまたはを使用する必要があることを示唆していますBeginInvoke

私はこれまでテキストの追加に問題があったことがないので、なぜそれが問題なのか理解できません。また、私が呼び出しについて読んでいることから、私はそれを理解していません。

誰かが私の状況でinvokeインスタンスを使用する方法を理解するのを手伝ってもらえますか?または、テキストボックスを追加する別の方法を教えてください。

4

2 に答える 2

6

通常、表示される例外はデバッグモードで実行したときに発生し、アプリケーションをリリースモードで実行した場合、例外が表示される可能性はほとんどありません。

ただし、読んだように、invokeを使用するのが最善です。このようなもの:

    private delegate void RefreshTextBox();

    private void DataReceivedHandler(object sender, SerialDataReceivedEventArgs e) {
        //this event is raised in an event separate from UI thread, 
        //so InvokeRequired must be checked and Invoke called to update UI controls. 
        if (this.InvokeRequired) {
            RefreshTextBox d = new RefreshTextBox(RefreshTextBoxResults);
            Invoke(d);
        } else {
            RefreshTextBoxResults();
        }
    }

    private void RefreshTextBoxResults() {
        string indata1 = serialPort1.ReadExisting();
        rx.Text = " ";
        rx.AppendText(Environment.NewLine + indata1);
    }

これが何かを呼び出すのを初めて見たとき、それに従うことはほとんど不可能ですが、よく見て、しばらく待ってください。それは理にかなっています。約束。:)

于 2012-08-22T20:19:47.577 に答える
5

GUIアプリケーションの更新は、GUIスレッドでのみ実行する必要があります。GUIコンポーネントを直接更新しようとする別のスレッドは、説明したエラーまたは一見ランダムな動作のいずれかを引き起こします。

&friendsの役割はInvoke、セカンダリスレッドがGUI更新をGUIスレッドに安全に転送できるようにすることです。GUIスレッドは、それらをキューから処理します。

あなたの場合(ここでWinFormsを想定):

rx.BeginInvoke(
      (Action)(() =>
      {
          rx.AppendText(Environment.NewLine + indata1);
      }));

BeginInvokeは非同期であるため、それを呼び出すスレッドは、同期している間、実際の更新が処理されるのを待たずに次に進みInvokeます。

于 2012-08-22T20:18:42.817 に答える