这就是我的系统的工作方式:
2台计算机正在使用不同的应用程序但使用相同的数据库(表:订单)。
第一台计算机正在下订单并将它们写入数据库, 第二台计算机需要每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系列或其他什么东西, 我不知道......
任何形式的帮助都非常棒,可以防止我的应用程序崩溃! 谢谢!
编辑:从我的视觉工作室运行应用程序后,我在几秒钟后得到这个(使用包括计时器滴答中的任务的解决方案):
答案 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。适用于那种操作