2017-06-06 53 views
0

在我的窗口中,我構建了3個圖表。他們沒有加載特別大的數據集,但窗口加載數據需要相當長的時間。在多線程工作時保持UI更新

爲了解決這個問題,我對它進行了多線程處理;每一組數據正在從它自己的線程加載:

private void Page_Loaded(object sender, RoutedEventArgs e) 
{ 
    Thread BasicAlertsThread = new Thread(new ThreadStart(BuildAlertsChart)); 
    Thread ResolvedAlertsThread = new Thread(new ThreadStart(BuildResolvedAlertsChart)); 
    Thread DetailedAlertsThread = new Thread(new ThreadStart(BuildAlertDetail)); 

    BasicAlertsThread.Start(); 
    ResolvedAlertsThread.Start(); 
    DetailedAlertsThread.Start(); 
} 

目前,我有每個線程時,他們做了指示組數據更新標籤的內容加載:

lblDescription.Dispatcher.Invoke(() => { lblDescription.Content += "Basic Report Chart loaded..."; }); 

這裏的其中一個線程正在執行的方法爲例。每個線程都做幾乎相同的事情(與正在查詢的數據有關的差異)。

private void BuildResolvedAlertsChart() 
{ 
    List<AlertsViewModel> ChartData = new List<AlertsViewModel>(); 
    DateTime StartingDate = DateTime.Now.AddMonths(-1); 

    using (ApplicationDbContext Context = new ApplicationDbContext()) 
    { 
     var Towers = Context.Towers.ToList(); 

     foreach (Tower Tower in Towers) 
     { 
      var AlertCount = Context.Alerts.Where(x => x.TowerId == Tower.Id && x.Date >= StartingDate && x.IsResolved == true).Count(); 
      if (AlertCount >= 1) 
      { 
       ChartData.Add(new AlertsViewModel { Alerts = AlertCount, Tower = Tower.Name }); 
      } 
     } 
    } 

    this.Dispatcher.Invoke(new Action(() => 
    { 
     ccResolvedAlerts.DataSource = ChartData; 
     XYDiagram2D Diagram = new XYDiagram2D(); 
     ccResolvedAlerts.Diagram = Diagram; 

     BarStackedSeries2D Series = new BarStackedSeries2D(); 
     Diagram.Series.Add(Series); 

     Series.Brush = Brushes.ForestGreen; 

     Series.DisplayName = "Resolved Alerts"; 
     foreach (AlertsViewModel Model in ChartData) 
     { 
      Series.Points.Add(new SeriesPoint(Model.Tower, Model.Alerts)); 
     } 

     lblDescription.Dispatcher.Invoke(() => { lblDescription.Text += "Resolved Alerts Chart loaded..."; }); 
    })); 
} 

雖然這個功能還沒那麼好,但因爲UI在更新此消息之前仍然非常活躍。

我知道如何在單個線程正在工作時更新消息,但是如何在3個線程仍然繁忙時執行此操作?

我可以像使用單個線程一樣使用回調函數,但是我擔心混淆了什麼是加載的問題,如果我使用來自3個不同線程的回調函數,哪些不是。

此外,使用這種方法,我注意到用戶界面沒有響應像拖動或滾動,直到所有的數據加載。

+0

它確實取決於非UI線程的功能。他們是否訪問UI線程?他們是否填寫了一個綁定的集合(並因此將事件提交給UI)等。 –

+0

基本上他們只是收集信息並在圖表中顯示。我已經更新了這個問題來展示一個例子。 – Ortund

+0

那麼,工作線程的示例代碼會做兩件事情 - 第一個塊從數據庫中檢索數據並在工作線程上運行。然而,將數據綁定到圖表的第二部分(Invoke內的整個塊)正在UI線程上執行,並且如果速度很慢......很快,看起來大部分代碼正在UI線程上同步執行,這解釋了無反應性。 –

回答

-1

也許你可以使用第四個線程來更新你的UI,如this答案建議。 也可以使用BackgroundWorker來保持你的UI「活躍」。