我创建了一个简单的应用程序,它每隔几秒钟从MSSQL数据库中读取数据,并使用db中的行绑定datagrid(如果db中有新项目)。 实际上正在使用两个应用程序,其中一个是将一些行插入数据库,这个应用程序不是主题的一部分,另一个正在显示那些行,所以如果我想保持第二个应用程序一直更新我会更新 数据网格每隔10秒保持更新,但有时会冻结,这真的很糟糕......现在我将通过图像解释:
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;
}
我想解决这个问题的方法是应用异步任务,但我不确定,因为我很唠叨,而且我不知道如何解决这个问题?我没有关于事情应该如何运作的逻辑,所以我可以选择一些更好的道路......所以任何一种帮助都会令人敬畏!
非常感谢! 干杯!
答案 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);
}
}