2011-10-20 9 views
16

私はチャットクライアントを構築していますが、dispatcherの使用方法は100%確信していません。そこで問題は、私は、次のような方法がありますされていますC#ディスパッチャの使用

public void LostConnection() 
{ 
    myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
} 

iはDispatcher.Invoke(myGUI.chatBox...)内のステートメントをsurrondする必要がありますか?私はどんな助けにも感謝します。 (私の頭の上から)このような

+0

こと依存しています...どのスレッドがそのメソッドを実行しますか?また、WPFを使用していることを確認するだけです。 ( 'Dispatcher'はそれだけで動作します。) – svick

+1

どのようなUIフレームワークを使用していますか?(WinForms、WPF、またはSL)それらの間に違いがある –

+0

svickが示唆するように、別のスレッドからあなたのUIに触れているかどうかによって異なります(非同期的に) – gideon

答えて

68

アプリは、メインUIスレッド(通常はManagedThreadId==1)を持っています。通常、チャットアプリケーションでは、イベントは他のスレッド(専用ソケットリスンスレッドまたはリスニングコードのスレッドプールスレッドのいずれか)に入ります。他のスレッドを取得するイベントからUIを更新する場合は、ディスパッチャを使用する必要があります。便利なテストは、Dispatcher.CheckAccess()メソッドで、コードがUIスレッドの場合はtrueを返し、他のスレッドの場合はfalseを返します。あなたが使用することができ、メインウィンドウにいる場合

using System.Windows.Threading; // For Dispatcher. 

if (Application.Current.Dispatcher.CheckAccess()) { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
} 
else { 
    Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(()=>{ 
     network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
    })); 
} 

:典型的な呼び出しは次のようになります

Dispatcher.BeginInvoke(... 

あなたが他の何らかの文脈にいる場合など、ビューモデル、次に使用:

Application.Current.Dispatcher.BeginInvoke( 

BeginInvokeを対起動
使用Invokeあなたは現在のスレッドがUIスレッドまで待つしたい場合UIスレッドで処理が完了するのを待たずに現在のスレッドを続行したい場合は、ディスパッチコードまたはBeginInvokeを処理しました。

メッセージボックス、ディスパッチャと起動/ BeginInvokeを:メッセージボックスが却下されるまで
Dispatcher.Invokeがあなたのスレッドをブロックします。
Dispatcher.BeginInvokeは、UIスレッドがMessageBox呼び出しでブロックされるまでスレッドコードが実行を継続できるようにします。

CurrentDispatcherとCurrent.Dispatcher!
Dispatcher.CurrentDispatcher私の理解では、UIスレッドではなく、現在のスレッドのDispatcherが返されます。通常、UIスレッドのディスパッチャに興味がありますか?Application.Current.Dispatcherは常にこれを返します。

追加注:
あなたは、多くの場合、ディスパッチャCHECKACCESSを確認するために行っている見つけている場合は、便利なヘルパーメソッドがある:として呼び出すことができ

public void DispatchIfNecessary(Action action) { 
    if (!Dispatcher.CheckAccess()) 
     Dispatcher.Invoke(action); 
    else 
     action.Invoke(); 
} 

DispatchIfNecessary(() => { 
    network_links.Add(new NetworkLinkVM(link, start_node, end_node)); 
}); 
+0

ねえ、私は指定していない、申し訳ありません、それはwpfアプリケーションであり、はいそれはクロススレッドです。バックエンドにデリゲートを設定してから、私のモデルに警告し、ディスパッチャメソッドを呼び出してguiインターフェイスを更新します。私はまだディスパッチャーを追加するためのintellesenseオプションを取得していないが、私はそれを強制的に実行しようとするとしようとします。みんなありがとう!その他のヒント? – Tombo890

+0

usingステートメントをインクルードし、Application.Current.Dispatcherを使用すると結果が得られます。 "バックエンド"がdllにある場合は、UIスレッドDispatcherをオブジェクトに渡して参照できるようにする必要があります。 – Ricibob

+0

@Ricibob、ちょうどニッキーニャンだと思うが、UIスレッドは必ずしも1のIDを持つ必要はないと思う。 – svick

2

何か作業をする必要があります:

public void LostConnection() 
{ 
    myGUI.Invoke 
     ((MethodInvoker)delegate 
    { 
     myGUI.chatBox.AppendText("Lost connection to room: "+ myGUI.UsernameText.ToString() + "\r\n"); 
    }); 
} 
+0

これはWinFormsにあります。この質問は明らかにWPFに関するものです。 – svick

+1

うん。それは質問から明らかではなかった。 –

関連する問題