web-dev-qa-db-ja.com

C#ディスパッチャーの使用

私はチャットクライアントを構築していますが、dispatcherの使用方法について100%確信が持てません。だから質問は、私はそのような方法を持っているということです:

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

(myGUI.chatBox... )内のステートメントをDispatcher.Invokeで囲む必要がありますか?私は助けに感謝します。

22
Tombo890

アプリにはメインUIスレッドがあります(通常は_ManagedThreadId==1_)。通常、チャットアプリでは、イベントは他のスレッド(専用のソケットリスンスレッドまたはリスニングコードのスレッドプールスレッド)で発生します。他のスレッドをプルするイベントからUIを更新する場合は、ディスパッチャーを使用する必要があります。ここで役立つテストは、コードがUIスレッド上にある場合はtrueを返し、他のスレッド上にある場合はfalseを返すDispatcher.CheckAccess()メソッドです。典型的な呼び出しは次のようになります。

_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(  
_

Invoke vs BeginInvoke
UIスレッドがディスパッチコードを処理するまで現在のスレッドを待機させる場合はInvokeを使用し、操作が完了するのを待たずに現在のスレッドを続行させる場合はBeginInvokeを使用しますUIスレッド。

MessageBox、Dispatchers、Invoke/BeginInvoke:
_Dispatcher.Invoke_は、MessageBoxが閉じられるまでスレッドをブロックします。
_Dispatcher.BeginInvoke_は、UIスレッドがMessageBox呼び出しで却下されるまでブロックする間、スレッドコードの実行を継続できるようにします。

CurrentDispatcher vs 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));
});
_
80
Ricibob

このようなもの(私の頭の上の)は動作するはずです:

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

_Application.Current.Dispatcher.BeginInvoke_およびobject.Invoke()メソッドに問題がありました。

これは私のために働いた:

_Dispatcher.CurrentDispatcher.BeginInvoke(new Action(() =>
{
     // code...
}));
_
0
MNicoll