2012-05-10 7 views
0

以下のコードは「リアルタイム」では機能しません。ボタンをクリックすると、バックグラウンドスレッドのデータセットが検証されます。すべてのデータが検証されるまで、真の「提出」を許可することはできませんが、テキストボックスをリアルタイムで更新したいと考えています。Parallel.ForEachを待っている間にリアルタイムでWinforms UIを更新する

代わりに、テキストボックスは、奇数で一気に更新されます。

何が起こっているのか想像してみましょう。私はメインスレッドで観測しているので、タスクが待ち受けをブロックしていますが、メインスレッドで更新する必要があるため、回避できません。

(もちろんこれは概念だけの証拠である)

やや関連する注意 - このコードはスレッドセーフが保証されていますか?ありがとう。

private Subject<int> _subject; 
    public Form1() 
    { 
     InitializeComponent(); 
    } 

    private int sleep = 2000; 
    private int i = 0; 
    private void LongRunningValidation(int num) 
    { 
     if (num % 2 == 0) return; 

     Thread.Sleep(sleep * (i++)); 

     _subject.OnNext(num); 
    } 


    private ConcurrentBag<int> _bag; 
    private void simpleButton1_Click(object sender, EventArgs e) 
    { 
     _subject = new Subject<int>(); 
     _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox); 

     _bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

     if(Validate()) 
     { 
      //submit 
     } 
    } 

    private bool Validate() 
    { 
     var task = Task.Factory.StartNew(StartValidationAsync); 

     task.Wait(); 

     return true; 
    } 

    private void StartValidationAsync() 
    { 
     Parallel.ForEach(_bag, LongRunningValidation); 
    } 

    private void UpdateTextBox(int i) 
    { 
     textEdit1.Text = textEdit1.Text + "," + i; 

    } 
} 

答えて

1

Validateメソッドは非同期ではなく、メインスレッドをブロックします。

public delegate void ValidatedHandler(bool validate); 
public event ValidatedHandler Validated; 

private void Validate() 
    { 
     var task = Task.Factory.StartNew(StartValidationAsync); 

     if (Validated != null) 
      Validated(true); 
    } 

をし、イベントにサブスクライブ:使用イベントをお試しください

private void simpleButton1_Click(object sender, EventArgs e) 
{ 
    _subject = new Subject<int>(); 
    _subject.SubscribeOn(Scheduler.TaskPool).ObserveOn(SynchronizationContext.Current).Synchronize().Subscribe(UpdateTextBox); 

_bag = new ConcurrentBag<int>() { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }; 

this.Validated += OnValidated; 
} 


public void OnValidated(bool validate) 
{ 
     if(validate) 
     { 
      //submit 
     } 
} 
+0

私はちょうどTask.ContinueWithを使用してから 'submit'しなければならないことに気付きましたが、これは私も同じ考えです。ご助力ありがとうございます。 – user981225

0

Windowsフォームは、バックグラウンドスレッドを実行していてもUIを自動的に更新しません。アップデートしたいものにUpdate()を呼び出してみてください。

+0

おかげでそれは問題ではありません。基本的な問題は、WaitブロックがUIスレッドをブロックするため、タスク(バックグラウンドスレッドの並列foreach)が完了するまでUpdateTextBoxメソッドが呼び出されないことです。 – user981225

関連する問題