糟糕的刷新屏幕导致应用程序性能问题

时间:2017-10-13 11:22:03

标签: c# wpf xaml user-interface task

这就是我的系统的工作方式:

2台计算机正在使用不同的应用程序但使用相同的数据库(表:订单)。

第一台计算机正在下订单并将它们写入数据库, 第二台计算机需要每5秒钟显示一次新订单。

我将很快描述(避免长篇文章)我需要实现的目标以及我现在是如何做到的:

  • 第二台计算机应用需要"去数据库"每5秒检查一次新订单并在屏幕上显示

当订单很多时,我经常这样做,我的应用程序崩溃了。

这就是我的应用现在的工作方式:

public MainWindow()
{

    try
    {
       InitializeComponent();
       this.WindowStartupLocation = WindowStartupLocation.CenterScreen;
       this.WindowState = WindowState.Maximized;
       //When app runs for first time get all orders
       var ordersList = OrdersController.GetOrders();


       collectionViewSource.Source = ordersList;
       collectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("NumberOfOrder"));
       DataContext = collectionViewSource;

       //Here I'm refreshing screen every 5 seconds




 DispatcherTimer timer = new DispatcherTimer();
       timer.Interval = TimeSpan.FromSeconds(5));
       timer.Tick += timer_Tick;
       timer.Start();

    }
    catch (Exception ex)
    {
       MessageBox.Show(ex.Message);
    }

}

void timer_Tick(object sender, EventArgs e)
{
    //Every 5 seconds get all orders from database
    var ordersList = OrdersController.GetOrders();
    collectionViewSource.Source = null;

    collectionViewSource.Source = ordersList;
    DataContext = collectionViewSource;
}

GetOrders方法:

public static List<Orders> GetOrders()
{
            DataServices.DB.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, DataServices.DB.Orders);

            var results = DataServices.DB.proc_Orders_GetAll().ToList();

            List<Orders> localOrders = new List<Orders>();

            foreach (var item in results)
            {
                Orders local = new Orders();
                local.Sender = item.Sender;
                local.Quantity = Convert.ToDecimal(item.Quantity);
                local.ArticleTitle = item.ArticleTitle;
                local.DateOfOrder = Convert.ToDateTime(item.DateOfOrder);
                lokalnen.Add(local);
            }
            return localOrders;
}

但是上面的代码不太好,如果有很多订单,它会导致我的应用程序崩溃。 可能是因为UI一次又一次地渲染

移动这个&#34;刷新工作&#34;到另一个任务可能会解决问题,所以我尝试了这样的事情:

首先创建新方法RefreshScreen,它可能如下所示:

private void RefreshScreen()
{
  var ordersList = OrdersController.GetOrders();
  collectionViewSource.Source = null;

  collectionViewSource.Source = ordersList;
  DataContext = collectionViewSource;
}

我将此RefreshScreen()移到了这样的新任务:

void timer_Tick(object sender, EventArgs e)
{
    //Instead old code where I set source of my list and of my datagrid directlly in timer tick now I moved it to new method and calling that method from a new task
   Task.Factory.StartNew(() => RefreshScreen())
        .ContinueWith(task =>
   {

   }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());

}

但这又让我的应用程序在一段时间后粉碎了...... 我真的不知道如何解决这个问题,也许是使用Observablle系列或其他什么东西, 我不知道......

任何形式的帮助都非常棒,可以防止我的应用程序崩溃! 谢谢!

编辑:从我的视觉工作室运行应用程序后,我在几秒钟后得到这个(使用包括计时器滴答中的任务的解决方案):

enter image description here

enter image description here

2 个答案:

答案 0 :(得分:0)

您应该在后台线程上查询数据库,但不能从后台线程访问DataContext属性或UI元素的任何其他属性。这就是为什么你得到“调用线程无法访问..”的例外。

您可以尝试启动在后台线程上调用Task方法的GetOrders()

void timer_Tick(object sender, EventArgs e)
{
    Task.Factory.StartNew(() =>
    {
        return OrdersController.GetOrders()
    }).ContinueWith(task =>
    {
        collectionViewSource.Source = task.Result;
        DataContext = collectionViewSource;
    }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext());
}

但是如果在查询完成后,ContinueWith委托中运行的代码很慢,那么除了获取更少的记录之外别无选择。

您还应确保未禁用UI虚拟化。您可能还想尝试不对结果进行分组。这也可能很慢。

答案 1 :(得分:-2)

尝试实施SignalR。适用于那种操作