2011-01-30 55 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 ..... 
    } 
}));