【发布时间】:2012-09-21 05:07:20
【问题描述】:
我有一个用 C# 和 WPF 创建的订单管理器应用程序。订单管理器应用程序需要与用完全不同的运输语言编写的运输应用程序来回通信。程序之间的通信方式是一个 XML 文件,它的 EnableShipping 属性是 0 或 1 和一个 SQL 数据库。
在我的订单管理器应用程序中,我有一个“开始发货”按钮并将 EnableShipping 属性从 0 更改为 1。发货应用程序正在循环并读取此值,开始发货其特定属性与字符串匹配的所有订单,将此属性更改为不同的字符串,并将不同的属性(状态已更改)标记为 1。
在我的订单管理器应用程序中,截至目前,我有一个线程不断循环并检查数据库中状态已更改属性为 1 的订单,对 UI 进行更改并写回数据库,状态已更改 = 0 .
这里有一些代码来显示我的订单管理器应用程序在线程中所做的事情。
while(true)
{
string enabled = null;
currentInstance = OrderManager.getCurrentInstance();
SqlCommand command = new SqlCommand("Select OrderNumber, BatchStatus from dbo.Orders where StatusChanged='1'", connection1);
SqlDataReader reader = command.ExecuteReader();
if (reader.HasRows)
{
while (reader.Read())
{
Int64 orderNum = (Int64)reader[0];
int index = linqForOrderIndex(orderNum);
string batchStatus = (string)reader["BatchStatus"];
SqlCommand statusChangedFalse = new SqlCommand("Update dbo.orders Set StatusChanged = '0' where OrderNumber = '" + orderNum + "'", connection2);
switch (batchStatus)
{
case "Untouched":
currentInstance.Orders[index].batchStatus = "Untouched";
break;
case "Batch Ready":
currentInstance.Orders[index].batchStatus = "Batch Ready";
break;
case "Shipped":
currentInstance.Orders[index].batchStatus = "Shipped";
break;
case "Error":
currentInstance.Orders[index].batchStatus = "Error";
break;
}
statusChangedFalse.ExecuteNonQuery();
Thread.Sleep(1000);
reader.Close();
reader = command.ExecuteReader();
}
currentInstance.Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Normal,
new Action(
delegate()
{
currentInstance.refreshTreeFilters();
currentInstance.refreshOrderCounts();
currentInstance.batchReadyView();
}
));
}
}
因此,即使您不确切知道代码中发生了什么,您也知道我必须不断检查数据库中状态更改的项目,对我的集合以及数据库中的这些项目进行处理,更新 UI,并不断重复该过程。
起初我认为一个好的旧线程会像我现在的代码一样工作,但是当我“工作”时 UI 变得没有响应。我在网上查看了一些后台工作人员代码,看看这是否可能是提高 UI 响应能力的好选择,但不知道这是否是一个好的解决方案,因为我需要不断地继续工作和更新 UI。
有什么想法或建议吗?感激不尽……
【问题讨论】:
-
除非有其他理由,否则请使用 BackgroundWorkers。由于“征求意见”的性质,以“不是真正的问题”结束。
-
无论如何,发布的这段代码也非常可能不是线程安全的,因为它看起来从后台线程和 UI 线程访问相同的数据同一时间。
-
我可以使用 BackgroundWorkers 永远循环并检查数据库中的 statusChanged 项目吗?
-
没有。那将是愚蠢的(BGW 是为 BG-Work->UI-result 设计的)。因此,排除并继续。它仍然不会改变我的其他 cmets。
-
因此,如果我有一个永远运行的线程,检查数据库中的更改并找到一些更改,然后在 UI-behind 代码中调用 backgroundworker 函数来“DoWork”......这是正确的接近它的方法?
标签: c# wpf multithreading backgroundworker threadpool