我有一个程序(WPF),每次执行测量,比方说,10秒。测量时间会有所不同,因此可能需要1秒或3秒,例如:
|o........|..o......|o........|...o.....|o..
|...measurement start o...measurement finished
我想要一个ProgressBar,它显示下一个测量任务何时开始。 此外,每次完成测量时,我都会将值添加到图形元素中以显示它们。
现在问题是:我有一个BackgroundWorker来检查它是否有时间进行测量。如果是时候,BackgroundWorker会启动执行测量的其他工作人员。
现在我刚刚实现了使用“bw.ReportProgress(0)”完成测量时显示数据的函数(0是一个没有用的虚拟值):
private void measure_interval_worker_DoWork(object sender, DoWorkEventArgs e)
{
BackgroundWorker bw = sender as BackgroundWorker;
DateTime timeToMeasure = DateTime.Now;
Boolean varsSaved = true; //if vars are saved
while (!measure_interval_worker.CancellationPending)
{
if (activeDevices.Count == 0 && varsSaved == false) //Devives are finished and vars aren't save yet
{
bw.ReportProgress(0); //In ProgressChanged the values are displayed
varsSaved = true;
}
if (DateTime.Now >= timeToMeasure && activeDevices.Count == 0) //If its time to measure and all devices are done with measurement
{
timeToMeasure = DateTime.Now + measure_gap; //Next time to measure
measure_workers = new List<BackgroundWorker>(); //Deleting the "old" workers?
foreach (var dev in devices)
{
//Add Key
varsSaved = false;
activeDevices.Add(dev.Key);
//And start worker
measure_workers.Add(new BackgroundWorker());
measure_workers[measure_workers.Count - 1].DoWork += measure_perform_DoWork;
measure_workers[measure_workers.Count - 1].RunWorkerAsync(dev.Key);
}
}
}
}
activeDevices只是一个列表,其中measure_workers删除了它们的名称,如果这样做,则activeDevices.Count == 0表示所有测量任务都已完成。
我现在尝试使用调度程序作为进度条,如:
this.Dispatcher.BeginInvoke((Action)delegate()
{
pbProgress.Value = (int)((timeToMeasure - DateTime.Now).TotalSeconds/ measure_gap.TotalSeconds * 100);
});
(在循环时把它放在measure_interval_worker里面)但是现在如果我启动了measure_interval_worker,GUI会冻结。
那我怎么解决这个问题呢?
我可以使用ReportProgress进行ProgressBar但是我在显示数据方面遇到了同样的问题,因为我不知道值何时可以显示。
答案 0 :(得分:1)
activeDevices
很可能不是线程安全的。如果它是List<T>
,那肯定不是。例如,使用ConcurrentBag。
此外,您不应该使用其他背景工作者的BackgroundWorker
方法创建DoWork
。它不会按预期工作(因为它不是从GUI线程创建的)。
答案 1 :(得分:0)
BackgroundWorker
是一种在.NET中使用多线程的快捷方式,但它可能不是您方案中的最佳候选者。任何时候你想要的东西超过BackgroundWorker
类所提供的东西,那么你需要考虑使用.NET 4.0中的Task
class或新的async
和{{3 .NET 4.5中的关键字。
使用这些类,您将能够一起运行所有测量,并让UI异步更新其进度。您可以在MSDN的以下页面中找到如何使用它们:
await
Start Multiple Async Tasks and Process Them As They Complete (C# and Visual Basic)