2009-03-18 10 views
1

マルチスレッドアプリケーションを開発するときに、繰り返しのコードを書く必要があるという点で、WPF(およびそれ以前のWindows Forms)で何かを見逃しましたか?アプリケーションのすべてのUIコントロールは、各プロパティを取得して設定するために余分なコード行を必要とします。WPF UIコントロールに対するマルチスレッドアクセスのオーバーヘッドはなぜですか?

internal delegate void SetElementIsEnabledDelegate(UIElement element, bool isEnabled); 
internal delegate void SetBrushesAndTextDelegate(Brush foregroundBrush, string message); 
internal delegate void SetCheckBoxCheckedDelegate(CheckBox checkbox, bool checkedValue); 
internal delegate void SetTextBoxTextDelegate(TextBox richTextBox, string text); 
internal delegate void SetRichTextBoxTextDelegate(RichTextBox textBox, string text); 

internal static void SetElementIsEnabled(UIElement element, bool isEnabled) 
{ 
    if (element.Dispatcher.Thread != Thread.CurrentThread) 
    { 
     // Execute the same method, but this time on the GUI thread 
     element.Dispatcher.Invoke(DispatcherPriority.Normal, new SetElementIsEnabledDelegate(SetElementIsEnabled), element, isEnabled); 
     return; 
    } 

    element.IsEnabled = isEnabled; 
} 

さらに30の代理人とそれにrespecitveメソッドを追加します。

私が知っている限り、スレッドを呼び出すすべての操作を行う必要性のない型の安全な方法はありません。また、これは、コントロールライブラリのフードの下で簡単に処理された可能性があるようです。私は間違った何かをしていますか、なぜMicrosoftはコントロールで呼び出されたスレッドを世話しないことにしましたか?

答えて

3

あなたは確かにそれを簡単にすることができます。あなた自身の別個のデリゲートタイプは一切必要ありません。.NET 3.5を使用している場合は、組み込みのFunc<...>Action<...>デリゲートを使用できます。自分で宣言してから使用することができます一般的に。

あなたが考慮するかもしれない他の事は(あなたがC#3を使用している場合、拡張メソッドとして)ヘルパー・メソッドを記述して、匿名メソッド(またはラムダ式)を使用されています

internal static void SetElementIsEnabled(UIElement element, bool isEnabled) 
{ 
    InvokeIfNecessary(element, delegate 
    { 
     element.IsEnabled = isEnabled; 
    }); 
} 

ヘルパーメソッドを次のようになります。

public static void InvokeIfNecessary(UIElement element, MethodInvoker action) 
{ 
    if (element.Dispatcher.Thread != Thread.CurrentThread) 
    { 
     element.Dispatcher.Invoke(DispatcherPriority.Normal, action); 
    } 
    else 
    { 
     action(); 
    } 
} 

(おそらくもBeginInvoke同等のものを含める必要があり、私はランデブーを必要としない限り、私は一般的にBeginInvokeを好む。。)

2

性能上の理由から簡単に言えば、なぜマルチスレッド化されたものだけがそれを必要とするのであれば、すべてのGUIアプリケーションはコードをマーシャリングすることによる性能の影響を受けなければならないのですか?

さらに、呼び出し回数が少なくて済むように、スレッドスレッドのチャタリングを少なくするようにアプリケーションを設計できます。

また、コードは特に効率的ではありません。私はあなたがWPFのためである間、私のコードは、Windowsフォームのためのより多くのだと思いますが、目的は同じです:

if (InvokeRequired) { 
    Invoke(new MethodInvoker(this.Function)); 
} else { 
    // do code 
} 

EDIT:より良いアプローチがあります。 Windowsでは、スレッドローカルストレージの問題のために、コントロールを作成したスレッドですべてのコントロールの更新が行われる必要があります。そして、これはすべての用途に必要なものではありません。

+0

は、パフォーマンスの観点から、UIコントロールが同じである場合に必要な一切マーシャリングはありません糸。 – sipwiz

+0

しかしマーシャリングのチェックが必要です。 –

+0

私は小切手のオーバーヘッドが小さいと思います。おそらく、2つのスレッドIDを比較するif文と同じくらい簡単です。 – sipwiz

0

ラムダを忘れないでください:

int myParam = 5; 

Dispatcher.BeginInvoke((Action)(() => SomeMethod(myParam))); 

ディスパッチャに隠されたインテリセンス方法もあります:

if(Dispatcher.CheckAccess()) 
    DoSomething(); 
関連する問題