In my Window, I'm building 3 charts. They aren't loading particularly large sets of data, but it takes a fairly long time for the window to load with the data.
To address this, I'm multithreading it; each set of data is being loaded from its own thread:
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();
}
Currently I have each thread updating a label's content when they're done to indicate that set of data is loaded:
lblDescription.Dispatcher.Invoke(() => { lblDescription.Content += "Basic Report Chart loaded..."; });
Here's the method that one of the threads is executing as an example. Each thread does pretty much the same thing (with differences relevant to the data that's being queried).
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..."; });
}));
}
This isn't working quite so well though because the UI still remains pretty inactive until its time to update this message.
I know how to update the message while a single thread is working, but how would I go about doing it while all 3 threads are still busy?
I could use a callback the same way as I'd do with a single thread, but I'm worried about confusing the issue of what's loaded and what isn't if I use the callback from 3 different threads.
Additionally, with this approach I've noticed the UI isn't responding to things like dragging or scrolling until all of the data is loaded.