なぜC#makeは、UIを更新するために別のスレッドのディスパッチャーを配置するのですか?
例:
Dispatcher.Invoke(() =
{
lblerrorName.Content = "";
});
常に「別のスレッドで実行中」という例外が発生しますが、UIスレッドにあるラベルを変更したい場合は、それが自動的に舞台裏で行われるのはなぜですか。
それは明白な理由なしに複雑さと追加のコードを追加します、なぜそれがこのようなものであるか誰かが説明できますか?
なぜそれが自動的に舞台裏で行われないのですか?.
これは、1つのコンポーネントの1つのプロパティに対して1つのアクションのみが関係している限り機能しますが、アクションが増えると、おそらく相互に依存するアクションが増えると、競合状態に陥るリスクが高くなります。明示的な「呼び出し」メカニズムは、トランザクションブラケットのように機能し、プログラマがアトミックの方法で複数のステートメントをグループ化できるようにします。
たとえば、WPFが「舞台裏」でコントロールアクションを呼び出す場合、各コントロールプロパティへのアクセスはそれ自体で遅延アクセスになります。これは、次のようなコードに非常に奇妙な効果をもたらします。
lblerrorName.Content = "ABC"; // this assignment is deferred
// ...
lblerrorName.Content = lblerrorName.Content + "DEF"; // "ABCDEF"? Maybe not.
このようなコードは、UIスレッド、UIスレッド外、またはデバッガーで段階的に実行すると、異なる動作を生成する可能性があります。
ただし、明示的な呼び出しにより、プログラマーはさまざまなコンポーネント操作ステートメントを意図的にまとめることができます。
Dispatcher.Invoke(() =
{
lblerrorName.Content = "ABC";
//...
lblerrorName.Content = lblerrorName.Content + "DEF"; // "ABCDEF"
});
したがって、これは自動化よりもエラーが発生しにくい方法です。
副次的なポイントとして、複数の制御データを操作する必要があるシナリオでは、おそらくループ内で、自動呼び出しは著しくパフォーマンスに影響を与える可能性があります。
プログラムが非UIスレッドからUIを更新したい場合、アプリケーションフレームワークには2つの選択肢があります。
後者のオプションは、非UIスレッドを続行し、場合によっては順次実行できる更新をさらに指定できるため、より用途が広いです。また、どちらのスレッドもリソースロックを保持している可能性がある間、他のスレッドを待機する必要がないため、デッドロックの問題を回避できます。
これらがC#フレームワークがDispatcherアプローチを使用する主な理由であると思います。
スレッドセーフの場合:WPFコントロールで使用されるスレッドアパートメントはSTAであり、コンポーネントを作成したスレッドのみがコンポーネントを変更できます。これは、継承してスレッドセーフではないオブジェクトのスレッドセーフを高めるために行われます。
バックグラウンドスレッドで何かを変更すると、プログラマに代わってスレッドエラーが発生する可能性があります。そのため、例外が発生し、元のSTAスレッドにマーシャリングし直す必要があります。自動ディスパッチがあると、この目的は実質的に無効になります
C#コンパイラを想定していて、IDEは、何をしていて、どのような目的であるかを認識しているか、または認識している必要があります。C#コンパイラは第3世代プログラミング言語です。そうではありません。わかりました。 IDE= WPFアプリケーションまたはWindowsフォームアプリケーションを実行しているため、テンプレートを使用すると、すぐに開始でき、ガイダンスが得られます。ただし、スレッドセーフな操作とそうでない操作を知ると、特定のシナリオでこれらを処理する方法には、非常に多くのインテリジェンスが必要です。C#コンパイラとIDEはドキュメントを読みません。もしそうなら、おそらく、それらが物事を処理する方法に同意しないでしょう。とにかく、彼らが行った選択を使用します。