2013-11-26 53 views
0

我有一個PROGRAMM(WPF),其執行測量每個,可以說,10秒。該測定時間而變化,所以它可能需要1秒或也許3秒,例如爲:而不ProgressChanged BackgroundWorker的更新GUI在WPF

|o........|..o......|o........|...o.....|o.. 

|...measurement start o...measurement finished 

我想有一個進度條,接下來的測量任務開始時顯示。此外,每次測量完成後,我將這些值添加到圖元素以顯示它們。

現在,這裏的問題是:我有一個BackgroundWorker,檢查如果時間來進行測量。如果它的時間,BackgroundWorker啓動其他執行測量的工人。

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); 
       } 
      } 
     } 
    } 

現在我有使用「bw.ReportProgress(0)」(0是沒有用的虛設值)只是實現的功能,以顯示數據在完成測量時, 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 while循環中),但現在如果我開始measure_interval_worker的GUI凍結。

那麼我怎樣才能解決這個問題?

我可以使用的進度的ReportProgress但後來我有同樣的問題,用於顯示數據,因爲我不知道什麼時候該值是準備好顯示。

+0

按下「停止」,並分析調用棧你的程序塊的GUI。整個計劃是否陷入僵局? – JeffRSon

+0

在目前的形式中,沒有保證measure_workers是完整的。我同意其他意見不要在BackgroundWorker中使用BackgroundWorker。我會在裏面使用BlockingCollection。如果CancellationPending我會設置e。取消= true; – Paparazzi

回答

0

BackgroundWorker是一種在.NET中使用多線程的快捷方式,但它可能不是而是是您場景中的最佳人選。任何時候你想要的東西比BackgroundWorker類提供了更多的,那麼你就需要考慮在.NET 4.0中,還是在.NET 4.5中新的asyncawait關鍵字使用無論是Task class

使用這些類,您將可以一起運行所有,並讓UI以異步方式更新其進度。您可以瞭解如何在MSDN上的以下網頁中使用它們:

Start Multiple Async Tasks and Process Them As They Complete (C# and Visual Basic)
Asynchronous Programming with Async and Await (C# and Visual Basic)

1

activeDevices很可能不是線程安全的。如果它是一個List<T>它肯定不是。例如,使用ConcurrentBag。

此外,您不應該從另一個背景工作者的DoWork方法創建BackgroundWorker。它不會按預期工作(因爲它不是從GUI線程創建的)。在調試器

+0

在後臺工作中使用backgroundworker可能會發生什麼問題(第二個背景工作與ui無關,它只是獲取measuredata並將其存儲到類中) – Stefan

+0

'ProgressChanged'和'RunWorkerCompleted'事件在線程中運行創建了'BackgroundWorker'(如果該線程支持這個,則WPF-GUI線程會這樣做)。這就是'BackgroundWorker'的實際用途,否則會造成混淆。儘管如此,這不應該是你的問題,但我覺得指出這一點很有用。 – JeffRSon

+0

我很感謝任何建議,所以使用後臺工作者的原因是他們主要有'ProgressChanged'和'RunWorkerCompleted'?而這個事件是在創建worker的線程中運行的(大多數情況下是ui線程)?所以最好使用像Sheridan所說的「任務」?我也看了一下ConcurrentBag,雖然在我的特殊情況下使用包沒有看到任何優勢 – Stefan

相關問題