2011-03-24 88 views
4

监测进展试图监视Parallel.ForEach环路我已经试过的建议提出this question可惜我已仍未能完成我想要的进步。在Parallel.ForEach

基本上我跑进当我试图执行的第一个问题建议(使用定时器)是,Parallel.ForEach方法是一个阻塞调用,因此计时器滴答回调没有发生。

所以我试着把Parallel.ForEach循环放在后台工作线程中。事实上允许发生计时器滴答事件,但直到ForEach操作完成后,我的计数器值才会更新。

这是代码的基本思想(带有背景工作)。

private StockList _StockListToProcess = null; 

private static Int64 ItemsProcessed = 0; 

private System.Windows.Threading.DispatcherTimer _timer = null; 

private System.ComponentModel.BackgroundWorker _backWorker = null; 

progressBar1.Minimum = 1; 
progressBar1.Maximum = this._StockListToProcess.Count; 

MainWindow.ItemsProcessed = 0; 

this._timer = new System.Windows.Threading.DispatcherTimer(); 
this._timer.Interval = TimeSpan.FromMilliseconds(100); 
this._timer.Tick += timer_Tick; 
this._timer.Start(); 

this._backWorker = new System.ComponentModel.BackgroundWorker(); 

this._backWorker.DoWork += delegate(object o, System.ComponentModel.DoWorkEventArgs args) 
{ 
    Parallel.ForEach(this._StockListToProcess, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, 
        (Stock stock) => 
         { 
          MyWebServiceClient serviceClient = new MyWebServiceClient(); 
          MyWebServiceClient.ResponseEnum result = (MyWebServiceClient .ResponseEnum)serviceClient.SetProductPricing(token.LoginName, token.LoginPassword, token.SiteID.ToString(), stock.ProductCode, stock.ProductPrice); 
          System.Threading.Interlocked.Increment(ref MainWindow.ItemsProcessed); 
         }); 

    this._timer.Stop(); 
}; 

private void timer_Tick(object sender, EventArgs e) 
{ 
    progressBar1.Value = MainWindow.ItemsProcessed; 
} 

我缺少什么?

+0

任何解决方案的完整源代码? – Kiquenet 2012-08-22 10:59:41

回答

1

虽然我很欣赏Enigmativity公布后一些搜索,我发现了我认为解决这个问题的正确实施的解决方案。一个不需要任何其他框架来实现。

有关完整概述please see this article.

+0

你能否带上这个答案,以便它不是一个外部链接?否则,如果链接死亡,那么这个答案也是如此。 – Enigmativity 2016-07-12 01:03:59

+0

以防万一,这里是一个将(希望)永远不死: http://web.archive.org/web/20160402204615/http://blog.stephencleary.com/2010/06/reporting-progress-from-参见tasks.html – Squirrelkiller 2016-08-18 14:31:32

0

,如果你在你的主线程使用普通的计时器,并通过ConcurrentDictionary传递信息怎么办?

4

我会试图说定时器和背景工作者的嵌套是造成你的悲伤。

如果可能的话,我建议你避免再赞成使用Reactive Extensions for .NET (Rx)的。

这是你的代码是什么样子,如果你做的事:

progressBar1.Minimum = 1; 
progressBar1.Maximum = this._StockListToProcess.Count; 

var itemsProcessed = 0; 
var updater = new Subject<Unit>(Scheduler.Dispatcher); 
updater.Subscribe(u => 
{ 
    itemsProcessed += 1; //Rx serializes "OnNext" calls so this is safe. 
    progressBar1.Value = itemsProcessed; 
}); 

Parallel.ForEach(this._StockListToProcess, new ParallelOptions() { MaxDegreeOfParallelism = 5 }, 
    (Stock stock) => 
     { 
      MyWebServiceClient serviceClient = new MyWebServiceClient(); 
      MyWebServiceClient.ResponseEnum result = (MyWebServiceClient .ResponseEnum)serviceClient.SetProductPricing(token.LoginName, token.LoginPassword, token.SiteID.ToString(), stock.ProductCode, stock.ProductPrice); 
      updater.OnNext(new Unit()); 
     }); 

updater.OnCompleted(); 

我没有使用的代码虚拟位的测试,它工作得很好所以,如果你够勇敢,你应该能够得到这个运行没有很多困难。 :-)