2011-11-01 2 views
1

でUIを更新しません:タスクは、私はこのコードを書いたWPF

public double SumRootN(int root) 
{ 
    double result = 0; 
    for (int i = 1; i < 10000000; i++) 
    { 
     tokenSource.Token.ThrowIfCancellationRequested(); 
     result += Math.Exp(Math.Log(i)/root); 
    } 
    return result; 
} 

private void btnclick_Click(object sender, RoutedEventArgs e) 
{ 
    tokenSource = new CancellationTokenSource(); 
    txttest.Text = ""; 

    var watch = Stopwatch.StartNew(); 
    List<Task> tasks = new List<Task>(); 
    var ui = TaskScheduler.FromCurrentSynchronizationContext(); 
    for (int i = 2; i < 20; i++) 
    { 
     int j = i; 
     var compute = Task.Factory.StartNew(() => 
     { 
      return SumRootN(j); 
     }, tokenSource.Token); 

     tasks.Add(compute); 

     var displayResults = compute.ContinueWith(
           resultTask => 
            txttest.Text 
            += "root " + j.ToString() + " " + 
             compute.Result.ToString() + 
             Environment.NewLine, 
           CancellationToken.None, 
           TaskContinuationOptions.OnlyOnRanToCompletion, 
           ui);    
    }  
} 

それは、WPFで動作しますが、私はこのコードをこのように書きました。

それは動作しません
tokenSource = new CancellationTokenSource(); 
var watch = Stopwatch.StartNew(); 
List<Task> tasks = new List<Task>(); 
var ui = TaskScheduler.FromCurrentSynchronizationContext(); 

Report 
    += ((Microsoft.Office.Interop.Excel.Range)_sheet.Cells[row, "B"]).Value2; 

var compute = Task.Factory.StartNew(() => 
      { 
       return Report;        
      }, tokenSource.Token); 

      tasks.Add(compute); 

      var displayResults 
       = compute.ContinueWith(resultTask => 
        txtReport.Text 
         += compute.Result.ToString() + 
          Environment.NewLine, 
        CancellationToken.None, 
        TaskContinuationOptions.OnlyOnRanToCompletion, 
        ui); 

txtReport.Textが正しい値を持っていますが、それは、操作の途中で表示されませんが、動作が終了するとtxtReportは、このコードは動作しませんなぜそれが

値のショー?一方、

+0

あなたのビューモデルは 'INotifyPropertyChanged'インターフェースを実装していますか? – ChrisF

+0

MVVMを使用していません。 – Arian

+0

プロパティが変更されたことをXAMLに依頼する必要があります。 – ChrisF

答えて

1

ContinueWithは、対象タスクが完了したときに非同期に実行継続を作成します。つまり、SumRootNの操作が完了した後にのみ結果を更新します。

1

私はTaskSchedulerで一度も働いたことがないので、あなたに直接フィードバックを与えることはできません。しかし、あなたの問題の記述からは、問題はUIスレッドがブロックされていることに非常に満足しています。コードが終了していない限り、UIは更新されません。

時間がかかる作業の場合は、BackgroundWorkerで行ってください。ただし、非同期からコントロールの値を直接設定することはできません。 Dispatcherを使用してコマンドをUIスレッドにルーティングするか、ProgressChanged -eventを使用してください。

次のコードは、BackgroundWorkerのを使用する方法を示しています

BackgroundWorker bgWorker = new BackgroundWorker() { WorkerReportsProgress=true}; 
bgWorker.DoWork += (s, e) => {  
    // Do here your calculations 
    // Use bgWorker.ReportProgress(); to report the current progress 
}; 
bgWorker.ProgressChanged+=(s,e)=>{  
    // Here you will be informed about progress and here it is save to set the labels value. 
}; 
bgWorker.RunWorkerCompleted += (s, e) => {  
// Here you will be informed if the job is done. 
}; 
bgWorker.RunWorkerAsync(); 
+0

しかし、私はwinformsのようなコードを使用し、それは動作します。 1'varui = TaskScheduler.FromCurrentSynchronizationContext();を使用します。 'スレッドを同期するにはどうしたらうまくいかないのですか? – Arian

1

このためのいくつかのトラブルシューティングのヒントがあります...あなたは...まず、あなたのコードが実際に配置されて

  1. をこれらの質問に答えることがあり? Button_click()コールでは?
  2. あなたのコードにbrekapointを入れたらTaskScheduler.FromCurrentSynchronizationContext();どのような種類のSynchronizationContextオブジェクトが見えますか? Dispatcherタイプですか?それとも他のタイプですか?
  3. TPLを使用する特別な理由はありますか?あなたはBackgroundWorkerDispatcherペアを使用していますか?