2017-02-10 3 views
0

UIの更新にかなりの時間がかかるとします。一例として、このダミーラベルはテキストを変更するのに1秒かかります。コントロールのSynchronizationContextポストキューの最後のもの以外の破棄

public class MyLabel : Label 
{ 
    public override string Text 
    { 
     get { return base.Text; } 
     set 
     { 
      Debug.WriteLine("Setting " + value); 
      Thread.Sleep(1000); 
      base.Text = value; 
     } 
    } 
} 

更新するタスクが複数ある場合は、それらの投稿がキューに入れられているようです。

var UIContext = SynchronizationContext.Current; 

for (int i = 0; i < 10; i++) 
{ 
    Task.Factory.StartNew((id) => 
    { 
     Debug.WriteLine(id); 
     Thread.Sleep((int)id*100); 
     UIContext.Post((label) => 
     { 
      myLabel1.Text = label.ToString(); 
     }, id); 
    }, i); 
} 

ラベルはポストがキューイングされている受信ようで、ラベルは最終的にそれらをすべて受信しますが、以前のものは取り扱われない必要ように、この例では、次のものが前のものを上書きします。理想的には、私は最後のもの以外のすべての投稿を無視したいと思います。キューに入れられたアイテムを確認して削除できますか?

+1

あなたはタイムマシンを求めています。彼らは実生活のようにソフトウェアで構築するのが難しいです。そうでなければ非常に単純な問題です。実行しなければならないジョブに追いつかないユーザーインターフェイスは、使用できないユーザーインターフェイスです。ユーザーはプログラムの制御を失い、タスクマネージャに頼らなくてもプログラムを終了することはできません。これは*バグ*ですが、修正する必要があります。 –

+0

同期コンテキストにポストするのではなく、 'Progress 'を使用してはいけませんか? –

答えて

0

私は間違った方向を考えたと思います。 SynchronizationContextキューを処理するのではなく、私自身のキューを作成しました。期待どおりに動作するようです。

public class MyLabel : Label 
{ 
    SynchronizationContext UIContext; 
    List<string> TextQueue; 
    public MyLabel() 
    { 
     UIContext = SynchronizationContext.Current; 
     TextQueue = new List<string>(); 
    } 

    public override string Text 
    { 
     get { return base.Text; } 
     set 
     { 
      Debug.WriteLine("Setting " + value); 
      Thread.Sleep(1000); 
      base.Text = value; 
     } 
    } 

    public void QueueTextChange(string text) 
    { 
     Debug.WriteLine("Request: " + text); 
     lock (TextQueue) 
     { 
      TextQueue.Add(text); 
     } 
     UIContext.Post((x) => { SetTextFromQueue();}, null); 
    } 

    void SetTextFromQueue() 
    { 
     string last=null; 
     lock (TextQueue) 
     { 
      if (TextQueue.Count > 0) 
      { 
       last = TextQueue.Last(); 
       TextQueue.Clear(); 
      } 
     } 
     if (last != null) 
      Text = last; 
    } 
} 

そして、他のスレッドが直接myLabel1.Text = ""を呼ぶが、以下のように、代わりに特別なキューイングメソッドを呼び出すことはありません。

myLabel1.QueueTextChange(label.ToString()); 
+0

または、Rxの[Throttle](http://www.introtorx.com/Content/v1.0.10621.0/13_TimeShiftedSequences.html#Throttle)などのビルトイン機能の1つを使用してイベントの速度を制限したり、またはConcurrentCollectionを使用してメッセージを受信します。 'Progress 'は、特定の同期コンテキストに依存することなく、それらを最初に報告するようにしました。 –

+0

'Progress'は存在しませんでした。私はそれを徹底的に調べます。提案ありがとう。 –

関連する問題