2011-01-30 57 views
2

我想從Parallel.For內更新WPF文本塊,但我不能。我使用調度員,但我想,我做錯了。所有的工作都是在第一時間完成的,然後textblock迭代地和快速地更新。這裏是我的代碼: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

因此,當我在下面回答Paul時,在後臺運行加載會導致性能的巨大損失。另外,Task.Create()必須位於較舊的.net版本中。你是否認爲這將有可能以並行的方式加載紋理並更新界面而不會在速度上做出可衡量的妥協?我希望我不要求太多;) – muku 2011-01-30 14:05:45

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()更改此代碼,儘管文本塊正在更新,但執行此代碼的時間卻大大增加,甚至有時會掛起。我相信在後臺運行加載可以開始其他繁重的操作,例如渲染紋理,這可能會降低加載速度,甚至會導致加載過程中斷。僅供參考,在單個線程上加載當前場景的紋理需要58s,並行。因爲花費34s。有沒有辦法保持性能和更新文本塊? – muku 2011-01-30 13:42:05

+0

固定。我不知道爲什麼它會比Parallel.For慢。如果你有VS2010旗艦版,Concurrency分析器可以在這裏幫助你很多 – 2011-01-30 20:36:24

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 ..... 
    } 
}));