2016-05-26 8 views
0

ネットワーク操作があり、ネットワークメッセージング中に一部のWPF要素が更新されています。Dispatcher.Invokeが非同期で実行されているか、まったく実行されていないと思われる場合があります。

「クライアント」はlistboxで、新しい接続があるたびに更新されています。

したがって、接続してください。

Dispatcher.Invoke(() => 
    { 
     listBox.Items.Clear(); 
    }); 

     for (i = 0; i < waitingMachines.Count; i++) { 
      sb.Clear(); 
      sb.Append((i + 1).ToString() + ") " + waitingMachines[i].Name + " - " + waitingMachines[i].CurrentMeasurement); 
      Dispatcher.Invoke(() => 
      { 
       listBox.Items.Add(sb.ToString()); 
      }); 
     } 

時にはlistBox.Items.Clear();がまったく実行されないように見える、と私は、リストボックスで2つの同じエントリで終わります。

Invokeを理解するには、次のInvokeを実行する前にリストをクリアする必要があります。どのように重複したエントリが得られているのか分かりません。

+1

まず、アイテム・ストリングのリストまたは配列を作成してから、単一のDispatcher呼び出しでクリア/追加操作を実行するのはなぜですか? – Clemens

+0

クリスタルボールは、「新しい接続があるたびに」実際には動作せず、このコードは毎秒何千回も実行されていると言います。リストボックスの非常に迅速な更新は、サイケデリックな効果を生むことがあります。 Thread.Sleep(100)を追加して診断すると、これは問題が非常に異なって見えます。 –

+0

@Clemens right ...それははるかに意味がある – pay

答えて

2

ほとんどの場合、通常の競合状態です。 Dispatcher.Invokeを使用しているので、コードブロックを複数のスレッドで同時に実行できると仮定します。両方のスレッドがこのブロックに入り、両方ともlistBox.Items.Clear()を次々に呼び出します。次に、両方ともリストボックスに項目を追加します。その結果、項目が重複します。

一般に、あなたは今何をする代わりにリストボックスを文字列の配列にバインドし、明示的にディスパッチャを呼び出すことなく、その配列を1つの呼び出しで割り当てることができるので、バインディングとMVVMパターンをWPFで読む必要があります。これはこの競合状態を避けるでしょう。

+0

ええと、2つのスレッドが同じ場所で同時に同じコードを実行していたとしても、私はまだそれが正しい順序で実行されたと思っていましたが、もしかして。私はこれを達成するためのより良い方法を検討します。編集:実際には心配しないで、彼らは不運な時に、正しい順序で実行しています。 – pay

+0

何らかの理由でバインディングを使用したくない場合(Clemensがコメント内で提案したものを使用) - クリアを組み合わせて、単一のディスパッチャコールでアイテムを追加します。 – Evk

+0

データバインディングを調べます。私は、それ自体で最も奇妙なスレッド状況を処理するだろうと思いますか? – pay

関連する問題