2


0

WinFormsスレッド間修正

私が他のスレッドからwinformを修正したいときはいつでも、私は使う必要があります

-> Invoke(delegate、params)

そのため、変更はwinform自身のスレッドで行われます。

guiを変更する必要があるすべての関数に対して、私は別のデリゲート関数が必要です。

必要なデリゲート関数の数を制限することを可能にするスキームはありますか? 私は一箇所でgui全体を処理するコントローラクラスを持っています、私はデリゲートを再利用することを考えました、しかしそれはひどいにおいがします。

私の質問はwinformが動く全ての言語に当てはまると思います。

4 Answer


6


C#3を使用している場合はラムダを使用でき、C#2では匿名デリゲートを使用できます。 振る舞いを再利用する必要がない場合、これらは構文を単純化します。 私がいつもすることの1つは、コントローラではなくフォームコードで同期を行うことです。 コントローラは、コントローラロジックよりもテクノロジ固有の「配管」問題に悩まされるべきではありません。

public void ResetFields(){// .NETバージョン<3.5の場合は "()=>"の代わりに "delegate"を使用.SelectedIndex = Defaults.ThirdChoice;}); }

// change Action to MethodInvoker for .Net versions less than 3.5
private void InvokeOnFormThread(アクション動作){if(IsHandleCreated)

慣例として、フォーム内のすべてのパブリックメソッドが "InvokeOnFormThread"を呼び出すようにします。代わりに、AOPを使用してフォーム上のパブリックメソッド呼び出しを傍受して "InvokeOnFormThread"を呼び出すこともできますが、上記の方法で十分に機能します(一貫性があり、フォームまたはUserControlsのパブリックメソッドで常に行う場合は忘れないでください)


2


既存の `+ System.Action `および ` System.Func +`デリゲートの使用を見てください:

control.Invoke(
    new Action(
        (i, s) => MessageBox.Show(String.Format(s, i))), 1, "{0}");
int iret = (int) control.Invoke(new Func(i1 => i1 + 1));


1


Michael Meadowsの答えは、GUIフォームを更新するロジックを一元管理する方法の良い例です。

少し前に、フロントエンドを同期するために多数のデリゲートを呼び出すパフォーマンス(これは簡単に取りつかれることがあります)については、GUI同期に関して同等のC(ネイティブ)Windowsアプリケーションよりも優れたソフトウェアを作成しました。 そして、それはすべて `+ BeginInvoke `と ` ThreadPool +`クラスのおかげです。

`+ Action <> `および ` Func <> `デリゲートと ` ThreadPool `クラスを使用することも有益であり、一般的な ` Invoke +`パターン(上記のMichaelが公開)を考慮してください。

public void TheGuiInvokeMethod(Control source, string text)
{
   if (InvokeRequired)
      Invoke(new Action(TheGuiInvokeMethod, source, text);
   else
   {
       // it is safe to update the GUI using the control
      control.Text = text;
   }
}

ここで、 `+ TheGuiInvokeMethod +`は実際にはフォームまたは他のコントロールに配置されます。


0


私はチェックをオフにして、私が使ったすべての呼び出しが安全であることを手動で確認することを思い出します。

特定のスレッドがどこにあるか(セマフォ)について保証していたため、またはそれらが他のプロセスで使用できる基礎となるAPI関数を呼び出したため、驚くほど多くのスレッドがクロススレッドと呼ばれる可能性があります。

私はまだMethodInvokerができるように、通常はコンテキストオブジェクトに対して多くの呼び出しをしてしまいました。

私はControl.Invokeで厄介なバグにも遭遇し、カスタムのinvokerライブラリを書くように促しました。