feat - 优化写入 添加写入锁定的哈希表 - 优化订单自动获取

master
SoulStar 4 days ago
parent 059e93c5c4
commit f2234fcabe

@ -540,32 +540,43 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
return;
}
//查找新订单(数据库中不存在的
var newOrders = new List<MesOrderInfo>();
//查找新订单或变更订单(全新订单 OR ProductOrder变更
var hasNewOrChanged = false;
foreach (var item in responsejson.Data)
{
var existing = databaseService._helper.Query(x => x.OrderNo == item.OrderNo && x.ProductCode == item.ProductCode);
var existing = databaseService._helper.Query(x =>
x.LineName == lineName && x.OrderNo == item.OrderNo && x.ProductCode == item.ProductCode);
if (existing == null || existing.Count == 0)
{
newOrders.Add(item);
//全新订单OrderNo + ProductCode 不存在)
hasNewOrChanged = true;
Log.Information($"自动刷新发现新订单:{item.OrderNo},物料:{item.ProductCode}ProductOrder:{item.ProductOrder}");
break;
}
else if (existing.Any(x => x.ProductOrder != item.ProductOrder))
{
//ProductOrder变更同OrderNo+ProductCode但ProductOrder不同
hasNewOrChanged = true;
Log.Information($"自动刷新发现订单ProductOrder变更:{item.OrderNo},物料:{item.ProductCode}" +
$"旧ProductOrder:{existing[0].ProductOrder}新ProductOrder:{item.ProductOrder}");
break;
}
}
if (newOrders.Count == 0)
if (!hasNewOrChanged)
return;
//先删除该机台的订单数据
//先删除该机台的订单数据再全量插入MES返回的所有订单
databaseService._helper.Delete(x => x.LineName == lineName);
//插入新订单到数据库并刷新界面
foreach (var item in newOrders)
foreach (var item in responsejson.Data)
{
item.ID = Guid.NewGuid().ToString();
item.InsertDate = DateTime.Now;
item.LineName = lineName;
databaseService._helper.Insert(item);
Log.Information($"自动刷新发现新订单:{item.OrderNo},物料:{item.ProductCode},自动执行");
}
Log.Information($"自动刷新已更新产线{lineName}的订单数据,共{responsejson.Data.Count}条");
//刷新界面显示
var items = databaseService._helper.QueryAll();
@ -577,8 +588,8 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
}
RefreshFilteredPanel();
//自动执行第一个订单
var firstNewOrder = newOrders[0];
//自动执行第一个订单responsejson.Data[0]已在上面循环中赋好ID
var firstNewOrder = responsejson.Data[0];
var deviceInfo = appConfig.deviceInfoConfig
.Where(x => x.Collectid == appConfig.StationCode && x.Name == lineName && x.Deleteflag == 0)
.ToList();

@ -57,6 +57,8 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
public TcpServer _TcpServer;
private DispatcherTimer _timer;
private Dictionary<string, DispatcherTimer> _inventoryTimers = new Dictionary<string, DispatcherTimer>();
private HashSet<string> _tickingDevices = new HashSet<string>();
private HashSet<string> _writingDevices = new HashSet<string>();
private ObservableCollection<RFIDRecord> _rfidHistoryRecords = new ObservableCollection<RFIDRecord>();
private RealReadDataImpl databaseService = RealReadDataImpl.Instance;
private System.Threading.Timer ReReadTimer;
@ -214,6 +216,9 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
/// <param name="tagInfos"></param>
private async void RecvIdentifyData_Instance(string iCombineId, List<TagInfo> tagInfos)
{
// 防重入:同一设备正在写入中,跳过本次标签读取
if (!_writingDevices.Add(iCombineId))
return;
var rfidInfo = rfidList.FirstOrDefault(x => x.deviceid == iCombineId);
var deviceInfo = Deviceinfo.FirstOrDefault(x => x.Deviceid == iCombineId);
@ -274,14 +279,13 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
//暂停订单自动刷新,防止写入过程中订单切换
WeakReferenceMessenger.Default.Send(string.Empty, "PauseOrderRefresh");
//处理写入字符串,并写入
/////////////////////////////////处理写入字符串,并写入////////////////////////////////////////
//var originBytes = tagInfos[0].EPC.Where(b => b != 0x00).ToArray();
bool writeflag = await rfidInfo.Set_Write(tagInfos[0].EPC, WriteData);
/////////////////////////////////处理写入字符串,并写入////////////////////////////////////////
state.WriteTime++;
//开启定时盘点和心跳
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
if (writeflag) //写入成功
{
@ -289,6 +293,9 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
state.IsVerify = true;
state.WriteTime = 0;
//开启定时盘点和心跳
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
//开始二次验证
await rfidInfo.Set_BeginIdentify();
@ -314,7 +321,10 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
else //写入失败
{
Log.Error($"第{state.WriteTime + 1}次写入失败,重试中...");
//重试前再读取一次标签
//开启定时盘点和心跳
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
await rfidInfo.Set_BeginIdentify();
//设置下次读取超时
@ -344,6 +354,7 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
await Task.Run(async () =>
{
await Task.Delay(1000);
//StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo!.Set_BeginIdentify();
deviceInfo.CurrentState = "盘点中";
});
@ -400,6 +411,10 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
StartInventoryTimer(iCombineId, deviceConfig.InventoryIntervalSeconds.Value);
await rfidInfo.Set_HeartBeat(5);
}
finally
{
_writingDevices.Remove(iCombineId);
}
}
/// <summary>
@ -812,20 +827,44 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
#region 定时盘点
/// <summary>
/// 启动定时盘点
/// 启动定时盘点(旧版 - 存在线程问题,已废弃)
/// </summary>
private void StartInventoryTimer(string deviceId, int intervalSeconds)
//private void StartInventoryTimer(string deviceId, int intervalSeconds)
//{
// StopInventoryTimer(deviceId);
// var timer = new DispatcherTimer
// {
// Interval = TimeSpan.FromMilliseconds(intervalSeconds)
// };
// timer.Tick += (s, e) => OnInventoryTimerTick(deviceId);
// timer.Start();
// //OnInventoryTimerTick(deviceId);
// _inventoryTimers[deviceId] = timer;
// Log.Information($"设备 {deviceId} 启动定时盘点,间隔 {intervalSeconds} ms");
//}
/// <summary>
/// 启动定时盘点(修复版)
/// 修复内容:
/// 1. DispatcherTimer 强制关联 UI 线程 Dispatcher避免在后台线程创建导致 Tick 不触发
/// 2. 参数更名为 intervalMilliseconds修正参数名与实际单位的误导
/// 3. StopInventoryTimer 也同步到 UI 线程执行,保证字典操作线程安全
/// </summary>
private void StartInventoryTimer(string deviceId, int intervalMilliseconds)
{
StopInventoryTimer(deviceId);
var timer = new DispatcherTimer
var uiDispatcher = System.Windows.Application.Current.Dispatcher;
uiDispatcher.Invoke(() =>
{
Interval = TimeSpan.FromMilliseconds(intervalSeconds)
};
timer.Tick += (s, e) => OnInventoryTimerTick(deviceId);
timer.Start();
//OnInventoryTimerTick(deviceId);
_inventoryTimers[deviceId] = timer;
Log.Information($"设备 {deviceId} 启动定时盘点,间隔 {intervalSeconds} ms");
StopInventoryTimer(deviceId);
var timer = new DispatcherTimer(DispatcherPriority.Normal, uiDispatcher)
{
Interval = TimeSpan.FromMilliseconds(intervalMilliseconds)
};
timer.Tick += (s, e) => OnInventoryTimerTick(deviceId);
timer.Start();
_inventoryTimers[deviceId] = timer;
Log.Information($"设备 {deviceId} 启动定时盘点,间隔 {intervalMilliseconds} ms");
});
}
/// <summary>
@ -842,16 +881,20 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
}
/// <summary>
/// 定时盘点回调
/// 定时盘点回调(加防重入保护)
/// </summary>
private async void OnInventoryTimerTick(string deviceId)
{
// 防重入:上一次 Set_BeginIdentify 未完成时跳过本次 Tick
if (!_tickingDevices.Add(deviceId))
return;
try
{
var rfid = rfidList.FirstOrDefault(x => x.deviceid == deviceId);
if (rfid != null)
{
//Log.Information($"设备 {deviceId} 执行定时盘点");
Log.Information($"设备 {deviceId} 执行定时盘点");
//await rfid.Set_StopIdentify();
//await Task.Delay(100);
await rfid.Set_BeginIdentify();
@ -861,6 +904,10 @@ namespace SlnMesnac.WPF.ViewModel.IndexPage
{
Log.Error($"设备 {deviceId} 定时盘点异常: {ex.Message}");
}
finally
{
_tickingDevices.Remove(deviceId);
}
}
#endregion

@ -81,7 +81,7 @@
//
"Name": "Line1",
//IP:Port
"ConnectStr": "192.168.0.7:20107",
"ConnectStr": "192.168.0.62:20108",
//
"Connectmode": "1",
// RFly_I160RFly_I160
@ -111,7 +111,7 @@
"Devicetype": "RFly_I160",
"Collectid": "102",
"Addr": "VM006-2",
"Deleteflag": "0",
"Deleteflag": "1",
"WriteDelaySet": 1000,
//"WriteCount": 3,
"InventoryIntervalSeconds": 5000,
@ -126,12 +126,13 @@
"StationCode": "102",
"MESConfig": "10.20.8.61:8001",
//"MESConfig": "10.20.8.61:8001",
"MESConfig": "127.0.0.1:5000",
//
"AutoOrderRefresh": true,
//
"OrderRefreshInterval": 300,
"OrderRefreshInterval": 30,
//MESMES
"MockMesResponse": ""
},

Loading…
Cancel
Save