8

私は技術レベルの従業員で、製造テスト環境でコーディングの一部を手伝っています。具体的な質問は、C# でイベントを処理することです。Button_click だけでなく、具体的には、シリアル ポートからのデータ ストリームがあり、シリアル ポートからのデータに応じてリアルタイムで UI を更新する必要がある場合です。たとえば、どちらも最終的に同じことを行う 2 つのアプローチがある場合、次の違いは何ですか。

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
        this.Invoke(new EventHandler(doSomething));
}

そして次のようなもの:

void OnGotData(object sender, EventArgs e) {...};
delegate void UpdateCallback(data d);
void doSomething(data d) {
   ...
  if (field.InvokeRequired) {
            UpdateCallback x = doSomething;
            this.Invoke(x, new object[] { d });
  }
  else {
            field.Text = d;
  }
   ...
}

トレードオフは何ですか?より複雑な 2 番目のアプローチは慣例の問題ですか?

4

1 に答える 1

1

私が理解している場合: 最初のアプローチ - 常に呼び出しを呼び出して UI を更新する

ここで、コントロールのハンドルが作成されたことがわかっていて、小さくて高速な UI の更新を行いたい場合は、最初のアプローチを使用できます。UI が責任を負いますが、Invoke を使用するとデッドロックが発生する可能性があります。コントロールのハンドルが作成されていない場合よりも、IsHandleCreated を呼び出して、Invoke が成功し、例外がスローされないようにする必要があります。IsHandleCreated が false を返す場合、Invoke を介して更新することはできず、ハンドルが作成されるまで待機する必要があります。

コントロールのハンドルが作成されていない場合、field.InvokeRequired が false を返す可能性があり、呼び出し時にfield.Text = d;コントロールのハンドルがバックグラウンド スレッドで作成され、メッセージ ポンプのないスレッドでコントロールが分離され、アプリケーションが不安定になるためです。

だから私にとっては、これがより良い方法です:

private void port_DataReceived(object sender, SerialDataReceivedEventArgs e) {
    input = (sender as SerialPort).ReadLine();
    if (input.Contains("look for this"))
    {   if (this.IsHandleCreated == false)
        {
        //do some stuff to proper handle creation or just wait for handle creation
        }

        this.BeginInvoke(new EventHandler(doSomething));
    }
}
于 2013-07-23T12:54:31.657 に答える