[英]Monitoring Progress in Parallel.ForEach
試圖監視Parallel.ForEach循環的進度我已經嘗試了在這個問題中提出的建議但不幸的是我仍然無法完成我想要的。
基本上我嘗試實現建議(使用計時器)時遇到的第一個問題是Parallel.ForEach方法是一個阻塞調用,因此沒有發生timer-tick回調。
所以我嘗試將Parallel.ForEach循環放在后台工作線程中。 這實際上允許timer-tick事件發生,但我的計數器值永遠不會更新,直到ForEach操作完成。
以下是代碼的基本概念(使用backgroundworker)。
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;
}
我錯過了什么?
我打算說,計時器和后台工作人員的築巢讓你感到悲痛。
如果可能的話,我建議你不要再使用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();
我使用一些虛擬代碼進行了測試,它工作得很好,如果你足夠勇敢,你應該能夠毫不費力地運行它。 :-)
雖然我很欣賞Enigmativity在經過一些搜索后發布的解決方案,但我發現了我認為解決這個問題的正確實現。 一個不需要任何其他框架來實現的。
有關完整概述, 請參閱此文章。
如果您在主線程中使用普通計時器並通過ConcurrentDictionary傳遞信息,該怎么辦?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.