试图监视Parallel.ForEach循环的进度我已经尝试了this question中提出的建议,但不幸的是我仍然无法完成我想要的。
基本上我尝试实现建议(使用计时器)时遇到的第一个问题是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;
}
我缺少什么?
答案 0 :(得分: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();
我使用了一些虚拟代码进行了测试,它工作得很好,如果你足够勇敢,你应该能够毫不费力地运行它。 : - )
答案 1 :(得分:1)
虽然我很欣赏Enigmativity在经过一些搜索后发布的解决方案,但我发现了我认为解决这个问题的正确实现。一个不需要任何其他框架来实现的。
答案 2 :(得分:0)
如果您在主线程中使用普通计时器并通过ConcurrentDictionary传递信息怎么办?