Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/299.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在多线程工作时保持UI更新_C#_Wpf_Multithreading - Fatal编程技术网

C# 在多线程工作时保持UI更新

C# 在多线程工作时保持UI更新,c#,wpf,multithreading,C#,Wpf,Multithreading,在我的窗口中,我正在创建3个图表。它们不会加载特别大的数据集,但窗口加载数据需要相当长的时间 为了解决这个问题,我对它进行了多线程处理;每一组数据都是从自己的线程加载的: private void Page_Loaded(object sender, RoutedEventArgs e) { Thread BasicAlertsThread = new Thread(new ThreadStart(BuildAlertsChart)); Thread ResolvedAlerts

在我的窗口中,我正在创建3个图表。它们不会加载特别大的数据集,但窗口加载数据需要相当长的时间

为了解决这个问题,我对它进行了多线程处理;每一组数据都是从自己的线程加载的:

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()
{
列表图表数据=新列表();
DateTime StartingDate=DateTime.Now.AddMonths(-1);
使用(ApplicationDbContext Context=new ApplicationDbContext())
{
var Towers=Context.Towers.ToList();
foreach(塔楼中的塔楼)
{
var AlertCount=Context.Alerts.Where(x=>x.TowerId==Tower.Id&&x.Date>=StartingDate&&x.IsResolved==true)。Count();
如果(AlertCount>=1)
{
添加(新的AlertsViewModel{Alerts=AlertCount,Tower=Tower.Name});
}
}
}
this.Dispatcher.Invoke(新操作(()=>
{
ccResolvedAlerts.DataSource=图表数据;
XYDiagram2D图=新的XYDiagram2D();
ccResolvedAlerts.Diagram=图表;
BarStackedSeries2D系列=新的BarStackedSeries2D();
图.系列.添加(系列);
Series.Brush=Brush.ForestGreen;
Series.DisplayName=“已解决警报”;
foreach(ChartData中的AlertsViewModel模型)
{
添加(新的序列点(Model.Tower、Model.Alerts));
}
lblDescription.Dispatcher.Invoke(()=>{lblDescription.Text+=“已加载已解析警报图表…”;});
}));
}
不过,这并不是很好,因为在更新此消息之前,UI仍然处于非常不活动的状态

我知道如何在单个线程工作时更新消息,但在所有3个线程仍然繁忙的情况下,我将如何进行更新

我可以像使用单个线程一样使用回调,但我担心如果使用来自3个不同线程的回调,会混淆加载了什么和没有加载什么的问题


此外,通过这种方法,我注意到在加载所有数据之前,UI不会对拖动或滚动之类的操作做出响应。

这实际上取决于非UI线程的功能。他们是否访问UI线程。他们是否填写了一个绑定的集合(从而向UI引发事件)等等。基本上,他们只是收集信息并在图表中显示这些信息。我已经更新了这个问题来展示一个示例。好吧,工作线程的示例代码有两件事-第一个块从db检索数据并在工作线程上运行。但是,将数据绑定到图表的第二部分(调用
中的整个块)在UI线程上执行,如果速度慢。。。简而言之,大部分代码似乎是在UI线程上同步执行的,这解释了无响应的原因。如果您的图表很大,您对此无能为力,因为所有3个线程都在UI线程上填充图表(通过
Dispatcher.Invoke
)。您可以尝试在multple
Dispatcher.Invoke(…,DispatcherPriority.Background)
之间拆分您的工作,以允许在调用之间处理其他具有更高优先级的操作,但我怀疑这会有多大帮助。顺便问一下,您的图表是交互式的(用户可以如何与它们交互)还是非交互式的?
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..."; });
    }));
}