每10秒刷新一次UI,导致我的应用冻结

时间:2018-01-15 12:28:47

标签: c# sql-server wpf asynchronous datagrid

我创建了一个简单的应用程序,它每隔几秒钟从MSSQL数据库中读取数据,并使用db中的行绑定datagrid(如果db中有新项目)。 实际上正在使用两个应用程序,其中一个是将一些行插入数据库,这个应用程序不是主题的一部分,另一个正在显示那些行,所以如果我想保持第二个应用程序一直更新我会更新 数据网格每隔10秒保持更新,但有时会冻结,这真的很糟糕......现在我将通过图像解释:

enter image description here

public partial class MainWindow : Window
{
    CollectionViewSource collectionViewSource = new CollectionViewSource();

    public MainWindow()
    {

        try
        {
            InitializeComponent();

            //First time app is runned I'm getting all orders from DB because I want to show some items if they exist, when app is started
            var ordersList = OrdersController.getAllOrders();

            //This code is used just to fill my collection with ordersList when app is started so I don't need to wait for 10 sec to databind it (look below method in timer)
            collectionViewSource.Source = ordersList;
            collectionViewSource.GroupDescriptions.Add(new PropertyGroupDescription("OrderNo"));
            DataContext = collectionViewSource;


            //In this method I'm binding my datagrid with ordersList, and I'm repeating this task every 10 seconds
            DispatcherTimer timer = new DispatcherTimer();
            timer.Interval = TimeSpan.FromSeconds(Convert.ToInt32(10));
            timer.Tick += timer_Tick;
            timer.Start();
        }
        catch (Exception ex)
        {
            MessageBox.Show(ex.Message);
        }

}



void timer_Tick(object sender, EventArgs e)
{
    try
    {
        //Here I'm setting source to my collection/datagrid
        var ordersList = OrdersController.getAllOrders();
        collectionViewSource.Source = null;

        collectionViewSource.Source = ordersList;
        DataContext = collectionViewSource;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}

// Method located in my Controller: OrdersController
public static List<Orders> getAllOrders()
{
    DataServices.MyApp.Refresh(System.Data.Linq.RefreshMode.OverwriteCurrentValues, DataServices.MyApp.Orders);
    var results = DataServices.MyApp.proc_Orders_GetAll().ToList();
    List<Orders> orders = new List<Orders>();

    foreach (var item in results)
    {
        LocalOrders lorders = new LocalOrders();

        lorders.Title = item.Title;
        lorders.Note = item.Note;
        lorders.Code = Convert.ToInt32(item.Code);
        lorders.CreatedAt = Convert.ToDateTime(item.CreatedAt);
        orders.Add(lorders);
    }
    return orders;
}

我想解决这个问题的方法是应用异步任务,但我不确定,因为我很唠叨,而且我不知道如何解决这个问题?我没有关于事情应该如何运作的逻辑,所以我可以选择一些更好的道路......所以任何一种帮助都会令人敬畏!

非常感谢! 干杯!

2 个答案:

答案 0 :(得分:0)

在UI线程上引发了Tick的{​​{1}}事件,这意味着您的应用程序将在从DispatcherTimer获取数据的过程中被冻结。您可以尝试通过启动TPL任务在后台线程上执行OrdersController

getAllOrders()

如果设置void timer_Tick(object sender, EventArgs e) { Task.Factory.StartNew(() => { return OrdersController.getAllOrders(); }) .ContinueWith(task => { if (task.Exception != null) { MessageBox.Show(ask.Exception.Message); } else { collectionViewSource.Source = task.Result; DataContext = collectionViewSource; } }, System.Threading.CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.FromCurrentSynchronizationContext()); } 的{​​{1}}属性,则必须获取较少的数据或尝试删除Source。我担心在显示大量数据时,使用CollectionViewSource并不会很好。

答案 1 :(得分:0)

使Tick处理程序异步,并在Task:

中执行长时间运行的操作
private async void timer_Tick(object sender, EventArgs e)
{
    try
    {
        var ordersList = await Task.Run(() => OrdersController.getAllOrders());

        collectionViewSource.Source = ordersList;
    }
    catch (Exception ex)
    {
        MessageBox.Show(ex.Message);
    }
}