2011-01-30 7 views
2

私はParallel.For内からWPFのテキストブロックを更新しようとしていますが、できません。私はディスパッチャーを使用しますが、私は間違ったやり方をしていると思います。すべての作業が最初に行われ、次にテキストブロックが反復的に更新されます。ここに私のコードは次のとおりです。Parallel.Forテキストブロックを更新する

Parallel.For(0, currentScene.Textures.Count, delegate(int i) 
     { 

      TextureObject texture = (currentScene.Textures[i]); 

      MainWindow.Instance.StatusBarText.Dispatcher.BeginInvoke(new Action(() 
       => MainWindow.Instance.StatusBarText.Text = "Loading Texture " + i 
       + " - " + texture.Name), null); 
      LoadTexture(texture); 
      } 
     }); 

答えて

1

Parallel.Forコールは、それ自体は、コールが戻るまで更新からそのスレッドをブロックし、あなたのUIスレッド上で行われています。代わりに、次の操作を行います。

Task.Create(delegate 
    { 
     Parallel.For(/* your current code */); 
    }); 

のBackgroundWorkerクラスはしかし、このシナリオのためのより適切な解決策になることがあります...

参考:http://social.msdn.microsoft.com/Forums/en/parallelextensions/thread/38d7a436-e1d1-4af8-8525-791ebeed9663

+0

私は下のポールに答えたので、バックグラウンドでロードを実行するとパフォーマンスが大幅に低下します。さらに、Task.Create()は古い.netリビジョンに存在する必要があります。テクスチャを並行して読み込み、測定可能な速度で妥協することなくUIを更新することは、どういうことかと思いますか?私は多くを求めないといいですね;) – muku

0

ロバートの権利が、ここで私はそれを書くだろう方法は次のとおりです。

Enumerable.Range(0, currentScene.Textures.Count).Select(i => 
    new Task(() => { 
     TextureObject texture = (currentScene.Textures[i]); 

     MainWindow.Instance.Dispatcher.BeginInvoke(new Action(() 
      => MainWindow.Instance.StatusBarText.Text = "Loading Texture " + i 
      + " - " + texture.Name), null); 
     LoadTexture(texture); 
    }); 
).Run(x => x.Start()); 

唯一の仕事は、他のタスクを座って待機することであるタスクを作成する必要はありません。

+0

私は.net 4を使い、Task.Createは利用できません。 Task.Factory.StartNew()でこのコードを変更しようとしましたが、テキストブロックが更新されていましたが、このコードの実行時間が大幅に増えました。バックグラウンドでロードを実行すると、ロード速度を落としたりロードプロセスを終了させたりするような、テクスチャのレンダリングのような、他の重い操作を開始することができます。参考までに、現在のシーンのテクスチャを1つのスレッドにロードするには、parallelsと58sが必要です。それには34秒かかります。パフォーマンスを維持し、テキストブロックを更新する方法はありますか? – muku

+0

固定。なぜこれがParallelよりも遅く実行されるのかわかりません。あなたがVS2010アルティメット版を持っているならば、同時性プロファイラはここで多くのお手伝いをすることができます –

0

Levy氏は、Parallel.For()への呼び出しはすべてのループ反復が完了するまでブロッキング呼び出しであると指摘しています。そのため、上で示唆したことを行うことができます。または単にバックグラウンドスレッドで呼び出しをラップすることもできます。

ThreadPool.QueueUserWorkItem(new WaitCallback(delegate(object arg) 
{ 
    Parallel.For(0, currentScene.Textures.Count, delegate(int i)   
    { 
     // The rest of your code ..... 
    } 
})); 
+0

ねえ、ありがとう。これらの方法を試しましたが、バックグラウンドスレッドで計算を実行すると、読み込みプロセスに大きな遅延が生じます。私の意図は、テクスチャをできるだけ高速にロードし、同時にUIを更新することです。私はこれが可能ではないはずです:( – muku

+0

あなたのコンピュータにはいくつのコアがありますか?また、オリジナルの実装と並列実装の合計時間は何ですか? – BonanzaDriver

+0

私は4コアCPUを持っています。並行して実行されている時間は34秒に短縮されています – muku