using Microsoft.AspNetCore.Mvc; using Microsoft.Extensions.DependencyInjection; using SlnMesnac.Business.@base; using SlnMesnac.Model.domain; using SlnMesnac.Model.dto.taskType; using SlnMesnac.Plc; using SlnMesnac.Serilog; using SlnMesnac.WCS.Global; using SlnMesnac.WCS.Library; using SqlSugar; using System.Threading.Tasks; namespace SlnMesnac.WCS.WCS { /// /// 根据条件创建任务 /// public class CreateTaskByRecord : BaseBusiness { private readonly SerilogHelper _logger; //3#车间上料点plc private readonly PlcAbsractFactory workShop3Plc; //2#计量室相关点位 private readonly PlcAbsractFactory workShop2Plc; private readonly ISqlSugarClient sqlSugarClient; public CreateTaskByRecord(IServiceProvider serviceProvider) : base(serviceProvider) { workShop3Plc = base.GetPlcByKey("workShop3Plc"); workShop2Plc = base.GetPlcByKey("workShop2Plc"); sqlSugarClient = serviceProvider.GetRequiredService(); _logger = serviceProvider.GetRequiredService(); //test(); } /// /// 启动扫描监听 /// public void StartPoint() { CreateTaskByReadPlcSignal(); //监听2#计量室旋转移栽plc信号,处理相关流程 var CreateProductTaskByLocationCodeThread = new Thread(ListeningWorkShop2TransplantingMachine); CreateProductTaskByLocationCodeThread.IsBackground = true; CreateProductTaskByLocationCodeThread.Name = "监听1#2#计量室旋转移栽plc信号处理连廊箱体旋转相关流程"; CreateProductTaskByLocationCodeThread.Start(); } /// /// 通过读plc条件创建任务 /// /// private void CreateTaskByReadPlcSignal() { Task.Run(() => { while (true) { try { if (workShop3Plc == null || !workShop3Plc.IsConnected) { _logger.Plc(DateTime.Now + "3#PLC未连接,请检查网络!"); continue; } #region 3#车间补四宫格空箱流程---监听3#1号光电状态 bool signal1 = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#大料箱进料为空")); if (signal1) { CreateSupplementBigPalletTask(); } #endregion 3#车间补四宫格空箱流程---监听3#1号光电状态 #region 从下料点到1-16机台送料任务--或者1-12移库任务 --监听3#2号光电状态 bool getBigFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#大料箱agv取料通知")); string machineCodeS = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#四宫格下料点机台号")).ToString(); string rfidS = workShop3Plc.readStringByAddress(StaticData.GetPlcAddress("3#四宫格下料点RFID号"), 12).Replace("\0", ""); int amount = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#四宫格下料点数量")); if (getBigFlag && machineCodeS != "0" && rfidS.Contains("SHS")) { CreatDeliverWorkShop3Task(machineCodeS, rfidS, amount); } #endregion 从下料点到1-16机台送料任务--或者1-12移库任务 --监听3#2号光电状态 #region 3#往2#计量室送料流程 bool getSmallFlag = workShop3Plc.readBoolByAddress(StaticData.GetPlcAddress("3#小料箱agv取料通知")); int smallAmount = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#小料箱下料点数量")); string machineCodeX = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#小料箱下料点机台号")).ToString(); string rfidX = workShop3Plc.readStringByAddress(StaticData.GetPlcAddress("3#小料箱下料点RFID号"), 12).Replace("\0", ""); if (getSmallFlag && machineCodeX != "0" && rfidX.Contains("SHX")) { if (machineCodeX == "1") { machineCodeX = "1006"; } CreatDeliverWorkShop2Task(machineCodeX, rfidX); } #endregion 3#往2#计量室送料流程 #region 3#补充小空托盘流程--3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务 int work3EmptyAmount = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#缓存皮带线库存数")); int busy3Flag = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#线体忙碌状态")); if ((work3EmptyAmount == 1 && busy3Flag == 0) || work3EmptyAmount == 0) { //3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务 CreateSupplySmallPalletToWorkshop3Task(); } #endregion 3#补充小空托盘流程--3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务 } catch (Exception ex) { _logger.Error($"CreateTaskByReadPlcSignal方法异常:" + ex.StackTrace); } finally { Thread.Sleep(1000); } } }); } /// /// 监听2#计量室旋转移栽plc信号,处理连廊箱体旋转相关流程 /// private void ListeningWorkShop2TransplantingMachine() { while (true) { try { if (workShop2Plc == null || !workShop2Plc.IsConnected) { continue; } #region 2#计量室料箱返回处理流程:空箱入缓存链条线,色粉派送至色粉存放点 //2#接驳位色粉派送至色粉存放点任务 if (workShop2Plc != null && workShop2Plc.IsConnected) { bool returnJudgeSignal = workShop2Plc.readBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取")); int busy2Flag = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态")); int Amount = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存链条线库存数")); //是否还有未在色粉库位的色粉箱体 bool anyTonerPallet = HasAnyTonerInLine(); if (returnJudgeSignal && busy2Flag == 0 && (Amount < 3 || anyTonerPallet)) { int type = 0; string rfid = ReadEpcStrByRfidKeyAndReturnType("2#Transplant", out type); if (type == 0 || type == 2) {//二次读取 rfid = ReadEpcStrByRfidKeyAndReturnType("2#Transplant", out type); } if (type == 1) //读到1个标签 { int hoistFloor = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#提升机当前层")); if (Amount < 3 && hoistFloor == 1) //如果提升机正好在1楼 { Thread.Sleep(300); } else if (anyTonerPallet) //有色粉空转 { Thread.Sleep(3500); } busy2Flag = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态")); if (busy2Flag == 0) { // 判断有无色粉, 如果没有色粉,wcs给 旋转移栽方向信号 写2,plc将料箱运到 缓存皮带线。 WmsPalletInfo? wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid); if (wmsPalletInfo != null && wmsPalletInfo.Amount > 0 && wmsPalletInfo.TonerFlag == 1) //携带色粉 { //注意:plc上旋转移栽必须锁住线体状态才可以,2#接驳位如果有满料,那么通知plc信号,plc在连廊不再把箱体放到旋转移栽上 //调度系统结合上面缓存链条线库存,如果上面低于3,那么空箱可以上来缓存线 workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#缓存空箱线体状态"), 1); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1); workShop2Plc.writeInt16ByAddress("DB100.DBW40", 1); bool createResult = CreateDeliverTonerTask(rfid); if (createResult) { //3色粉上提升机移栽等待 _logger.Info($"2#移栽===={rfid}携带色粉去往色粉库位"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 3); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } else { //色粉库位无空闲位置,空转一圈 //2空箱转运 _logger.Info($"2#移栽===={rfid}携带色粉,色粉库位无空闲位置,空转一圈"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } } else if (wmsPalletInfo != null && wmsPalletInfo.Amount > 0 && wmsPalletInfo.TonerFlag == 0) //携带满料 { //2转运 _logger.Info($"2#移栽===={rfid}携带满料,空转一圈"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } else if (wmsPalletInfo != null && wmsPalletInfo.Amount == 0) //空托盘 { if (Amount < 3) { //1上提升机去缓存线 _logger.Info($"2#移栽===={rfid}空箱,去缓存区"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 1); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } else { //2空箱转运 _logger.Info($"2#移栽===={rfid}空箱,空箱转运"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } } } } else if (type == 0) //读到0个标签 { //RFID 未读到报警(2#移栽平台处) workShop2Plc.writeBoolByAddress("DB100.DBX42.1", true); _logger.Error("RFID 未读取报警(2#移栽平台处)"); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); //没读到2空箱转运 // _logger.Info($"1#移栽====没读到,空箱转运"); //workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 1); //workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#移栽平台任务"), 2); //workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } else if (type == 2) //串读 { //RFID 串读报警(2#移栽平台处) workShop2Plc.writeBoolByAddress("DB100.DBX42.0", true); _logger.Error("RFID 串读报警(2#移栽平台处)"); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运回RFID读取"), false); } } } #endregion 2#计量室料箱返回处理流程:空箱入缓存链条线,色粉派送至色粉存放点 #region 1#连廊料箱在计量室连廊移栽处理流程:wcs读RFID判断是否空箱,空箱下plc信号旋转,非空箱通知plc上提升机计量室 if (workShop2Plc != null && workShop2Plc.IsConnected) { bool returnJudgeSignal = workShop2Plc.readBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取")); int busy1Flag = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("1#提升机忙碌状态")); if (returnJudgeSignal && busy1Flag == 0) { //test int type = 0; string rfid = ReadEpcStrByRfidKeyAndReturnType("1#MetrologyRoom", out type); if (string.IsNullOrEmpty(rfid)) { rfid = ReadEpcStrByRfidKeyAndReturnType("1#MetrologyRoom", out type); } if (type == 1) { // 判断有无料, 如果没有料,wcs下发空箱旋转信号,有料,通知plc上提升机计量室 WmsPalletInfo? wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid); if (wmsPalletInfo != null && wmsPalletInfo.Amount > 0 && wmsPalletInfo.TonerFlag == 1) //携带色粉 { //2空箱转运 _logger.Info($"1#移栽===={rfid}携带色粉,空箱转运"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 2); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); } if (wmsPalletInfo != null && wmsPalletInfo.Amount > 0 && wmsPalletInfo.TonerFlag == 0) //携带满料 { //1#移栽平台任务(1上提升机,2空箱转运) _logger.Info($"1#移栽===={rfid}携带满料,去提升机计量室"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 1); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); } else if (wmsPalletInfo != null && wmsPalletInfo.Amount == 0) { //1#移栽平台任务(1上提升机,2空箱转运) _logger.Info($"1#移栽===={rfid}空箱,空箱转运"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 2); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); } } else if (type == 0) { //RFID 未读到报警(1#移栽平台处) workShop2Plc.writeBoolByAddress("DB100.DBX42.3", true); _logger.Error("RFID 未读取报警(1#移栽平台处)"); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); //没读到,当成空箱子旋转一圈 //1#移栽平台任务(1上提升机,2空箱转运) // _logger.Info($"1#移栽====没读到,空箱转运"); //workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("1#移栽平台任务"), 2); //workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); } else if (type == 2)//串读 { //RFID 串读报警(1#移栽平台处) workShop2Plc.writeBoolByAddress("DB100.DBX42.2", true); _logger.Error("RFID 串读报警(1#移栽平台处)"); workShop2Plc.writeBoolByAddress(StaticData.GetPlcAddress("2#料箱运进计量室RFID读取"), false); } } } #endregion 1#连廊料箱在计量室连廊移栽处理流程:wcs读RFID判断是否空箱,空箱下plc信号旋转,非空箱通知plc上提升机计量室 #region 暂时不使用--色粉存放点空托盘派送至2#接驳位 /////如果色粉存放点可用空库位小于等于2个,并且有空托盘在库位,判断2#缓存链条线库存(容量3)低于2个,并且无 从3#接驳位到2#接驳位的送料任务或 色粉存放点到2#缓存链条线任务, /////2.生成色粉存放点到2#缓存链条线任务 //int canUseAmount = sqlSugarClient.Queryable().Count(it => it.EquipType == 7 && it.EquipStatus == 0 && string.IsNullOrEmpty(it.ContainerCode)); ////判断色粉存放处是否有空托盘 //WcsBaseEquip? startEquip = sqlSugarClient.Queryable().InnerJoin( // (wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode && wpi.Amount == 0 && wbe.EquipStatus == 0) // .Where(wbe => wbe.EquipType == 7 && !string.IsNullOrEmpty(wbe.ContainerCode)).First(); //if (canUseAmount < 2 && startEquip != null) //{ // int cacheLineAmount = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存链条线库存数")); // bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.EmptyReturnFromTonerTask || it.TaskType == StaticTaskType.TransferMaterialMetrologyRoomBoxTask); // if (cacheLineAmount < 2 && !hasTask) // { // try // { // sqlSugarClient.AsTenant().BeginTran(); // WcsTask task = new WcsTask(); // task.TaskType = StaticTaskType.EmptyReturnFromTonerTask; // task.CurrPointNo = startEquip.AgvPositionCode; // task.EndPointNo = "2DeliverMetrologyRoomPoint"; // task.TaskStatus = 0; // task.CreatedTime = DateTime.Now; // task.CreatedBy = "wcs"; // task.TaskName = "色粉存放点空托盘派送至2#接驳位"; // task.PalletInfoCode = startEquip.ContainerCode; // int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); // WcsTaskLog wcsTaskLog = CoreMapper.Map(task); // wcsTaskLog.Id = id; // startEquip.EquipStatus = 1; // sqlSugarClient.Updateable(startEquip).ExecuteCommand(); // sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); // sqlSugarClient.AsTenant().CommitTran(); // _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); // } // catch (Exception ex) // { // sqlSugarClient.AsTenant().RollbackTran(); // _logger.Error($"色粉存放点空托盘派送至2#接驳位任务提交事务异常{ex.Message}"); // } // } //} #endregion 暂时不使用--色粉存放点空托盘派送至2#接驳位 } catch (Exception ex) { _logger.Error($"ListeningWorkShop2TransplantingMachine方法异常:" + ex.StackTrace); } finally { Thread.Sleep(1000 * 1); } } } #region 任务流程 /// /// 3#车间补四宫格空箱流程 /// private async void CreateSupplementBigPalletTask() { try { //判断agv是否有来这里的任务 bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.SupplyEmptyPalletTask && it.EndPointNo == "3SuppleEmptyPalletPoint"); if (hasTask) { //_logger.Info("Agv已有3#车间补四宫格空箱任务"); return; } #region 寻找机台空托盘 WmsBaseLocation? startLocation = null; //todo:优化点:为避免送料时尽可能少的移库任务,因此在这里可以先读取下一个料包要去的机台号,提前调度这里的空箱 //string nextGoMachineCode = workShop3Plc.readInt16ByAddress(StaticData.GetPlcAddress("3#实时机台号")).ToString(); //bool hasAny = StaticData.WmsMachineInfos.Any(x => x.MachineCode == nextGoMachineCode && x.WorkshopId == 3); //if (hasAny) //{ // int machineId = StaticData.WmsMachineInfos.First(x => x.MachineCode == nextGoMachineCode).MachineId; // if (machineId >= 12 && machineId <= 16) // { // //12 - 16号机台都送往12号机台 // machineId = 12; // } // //判断该机台有无空料箱,优先补充 // string sql = $"SELECT wbl.* FROM wms_base_location wbl join wms_pallet_info wpi on wbl.container_code = wpi.pallet_info_code where wbl.container_code is not null and wbl.container_code!='' and wbl.location_status=0 and wbl.machineid ={machineId} and wpi.amount=0"; // List startLocations = sqlSugarClient.Ado.SqlQuery(sql).OrderByDescending(x => x.MachineId).ToList(); // if (startLocations.Count > 0) // { // startLocation = startLocations[0]; // } //} //1-12机台,优先12 if (startLocation == null) { string sql = "SELECT wbl.* FROM wms_base_location wbl join wms_pallet_info wpi on wbl.container_code = wpi.pallet_info_code where wbl.container_code is not null and wbl.container_code!='' and wbl.location_status=0 and wbl.machineid<=12 and wpi.amount=0"; List emptyLocations = sqlSugarClient.Ado.SqlQuery(sql).OrderBy(x => x.MachineId).ToList(); if (emptyLocations.Count == 0) { _logger.Info("暂时没有可用空托盘库位"); //todo报警 return; } //暂时排序,后期结合小料正在生产的计划提前调度要配送机台的空托盘,或者可以根据实际位置调度最近的空料箱 startLocation = emptyLocations.Last();//从12机台开始送 //startLocation = emptyLocations.First();//从头开始送 } WcsBaseEquip? endEquip = sqlSugarClient.Queryable().Where(it => it.EquipNo == "3SuppleEmptyPalletPoint").ToList().First(); #endregion 寻找机台空托盘 sqlSugarClient.AsTenant().BeginTran(); WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.SupplyEmptyPalletTask; task.TaskName = StaticTaskType.GetDescription(task.TaskType); task.CurrPointNo = startLocation.AgvPositionCode; startLocation.LocationStatus = 1; sqlSugarClient.Updateable(startLocation).ExecuteCommand(); // task.NextPointNo = agvEquip.AgvPositionCode; task.EndPointNo = endEquip.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.PalletInfoCode = startLocation.ContainerCode; int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"生成3#车间补四宫格空箱流程异常{ex.Message}"); } } /// /// 从下料点到1-16机台送料任务 创建移库任务 /// private async void CreatDeliverWorkShop3Task(string machineCode, string rfid, int amount) { try { bool hasMachineCode = StaticData.WmsMachineInfos.Any(x => x.MachineCode == machineCode); if (!string.IsNullOrEmpty(rfid) && hasMachineCode) { //判断该料箱是否已经有送料任务 bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.TransferMaterialBoxTask && it.PalletInfoCode == rfid); if (hasTask) { _logger.Info($"该托盘{rfid}已有下料点到1-16机台送料任务"); return; } //判断该托盘是否已经在库里 bool isInLocation = sqlSugarClient.Queryable().Any(it => it.ContainerCode == rfid); if (isInLocation) { //todo推送报警 _logger.Info($"该托盘{rfid}已存在库位,请检查托盘号是否重复"); return; } List AllWmsBaseLocationList = await sqlSugarClient.Queryable().Where(x => x.MachineId <= 12).ToListAsync(); WmsBaseLocation? targetLocation; // 根据机台号寻找终点库位、判断机台的两个库位是否有空位置、没有的话先生成移库任务 targetLocation = GetTargetLocation(machineCode, AllWmsBaseLocationList); if (targetLocation == null) { //todo:推送预警 _logger.Info($"机台:{machineCode}没有可用空库位,无法配送"); return; } #region 二次核查确认目标库位是否有托盘 bool hasPallet = sqlSugarClient.Queryable().Any(x => x.LocationCode == targetLocation.LocationCode && string.IsNullOrEmpty(x.ContainerCode)); if (!hasPallet) { _logger.Info($"库位:{targetLocation.LocationCode}有托盘暂不处理"); return; } #endregion 二次核查确认目标库位是否有托盘 WcsBaseEquip startEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "3DeliverBigGoodsStartPoint"); WmsPalletInfo wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid); WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.TransferMaterialBoxTask; task.CurrPointNo = startEquip.AgvPositionCode; task.EndPointNo = targetLocation.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "下料点到1-16机台送料任务"; task.PalletInfoCode = rfid; task.MachineCode = machineCode; sqlSugarClient.AsTenant().BeginTran(); try { int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; targetLocation.LocationStatus = 1; int LockFlag = sqlSugarClient.Updateable(targetLocation).ExecuteCommand(); sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); while (LockFlag<=0) { LockFlag = sqlSugarClient.Updateable(targetLocation).ExecuteCommand(); } #region 修改托盘信息 if (wmsPalletInfo != null) { wmsPalletInfo.Amount = amount != 0 ? amount : 1; wmsPalletInfo.UpdatedTime = DateTime.Now; sqlSugarClient.Updateable(wmsPalletInfo).ExecuteCommand(); } #endregion 修改托盘信息 sqlSugarClient.AsTenant().CommitTran(); workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#大料箱agv取料通知"), false); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"生成3#车间从下料点到1-16机台送料任务提交事务异常{ex.Message}"); } } } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"生成3#车间从下料点到1-16机台送料任务异常{ex.Message}"); } } /// /// 从3#接驳位到2#计量室接驳位的送料任务 /// private void CreatDeliverWorkShop2Task(string machineCode, string rfid) { try { bool hasMachineCode = StaticData.WmsMachineInfos.Any(x => x.MachineCode == machineCode); if (!string.IsNullOrEmpty(rfid) && hasMachineCode) { //判断agv是否有来这里的任务 bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.TransferMaterialMetrologyRoomBoxTask && it.PalletInfoCode == rfid); if (hasTask) { _logger.Info($"该托盘{rfid}已有3#接驳位到2#计量室接驳位的送料任务"); return; } //限制送料任务生成数量 int transTaskAmount = sqlSugarClient.Queryable().Where(it => it.TaskType == StaticTaskType.TransferMaterialMetrologyRoomBoxTask).ToList().Count(); if (transTaskAmount > 2) { _logger.Info($"小托盘任务生成任务已大于上限(上限为2)!请稍等,所有小车同时运输小托盘将会导致卡死!"); return; } //起点库位 3#车间小料箱取送货接驳点 WcsBaseEquip startEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "3DeliverSmallGoodsPoint"); //终点库位 2#车间计量室接驳点 WcsBaseEquip endEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "2DeliverMetrologyRoomPoint"); WmsPalletInfo wmsPalletInfo = sqlSugarClient.Queryable().First(it => it.PalletInfoCode == rfid); sqlSugarClient.AsTenant().BeginTran(); WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.TransferMaterialMetrologyRoomBoxTask; task.CurrPointNo = startEquip.AgvPositionCode; // task.NextPointNo = agvEquip.AgvPositionCode; task.EndPointNo = endEquip.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "3#接驳位到2#计量室接驳位的送料任务"; task.PalletInfoCode = rfid; task.MachineCode = machineCode; int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); #region 修改托盘信息 if (wmsPalletInfo != null) { wmsPalletInfo.TonerFlag = 0; wmsPalletInfo.Amount = 1; wmsPalletInfo.UpdatedTime = DateTime.Now; sqlSugarClient.Updateable(wmsPalletInfo).ExecuteCommand(); } #endregion 修改托盘信息 sqlSugarClient.AsTenant().CommitTran(); workShop3Plc.writeBoolByAddress(StaticData.GetPlcAddress("3#小料箱agv取料通知"), false); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); } } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"3#接驳位到2#计量室接驳位的送料任务{ex.Message}"); } } /// /// 3#车间从色粉存放点补充小托盘任务 或者 3#车间从2#接驳位补充小托盘任务 /// .wcs检测到 3#缓存皮带线库存数 (容量2)不满时,且色粉存放处有空托盘时,优先生成色粉存放处补充小料箱任务 ///2.如果色粉存放处无空托盘,且2#缓存链条线库存数 大于0个,并且 2#线体忙碌状态 0时,2s后 2#线体忙碌状态 0时,wcs把 2#线体忙碌状态 改为1,wcs下发缓存链条线 2#出一个空托盘信号(plc自己复位), wcs并且生成一个3#补充空托盘任务呼叫agv /// private void CreateSupplySmallPalletToWorkshop3Task() { try { //判断是否已经有空托盘补充任务 bool hasTask = sqlSugarClient.Queryable().Any(x => x.TaskType == StaticTaskType.SupplySmallPalletTask || x.TaskType == StaticTaskType.SupplySmallPalletFromTonerTask); if (hasTask) { return; } //判断色粉存放处是否有空托盘 WcsBaseEquip? emptyPalletEquip = sqlSugarClient.Queryable().InnerJoin( (wbe, wpi) => wbe.ContainerCode == wpi.PalletInfoCode && wpi.Amount == 0 && wbe.EquipStatus == 0) .Where(wbe => wbe.EquipType == 7 && !string.IsNullOrEmpty(wbe.ContainerCode)).OrderBy(wbe => wbe.Id).First(); if (emptyPalletEquip != null) //从色粉存放处生成补充空托盘任务 { WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.SupplySmallPalletFromTonerTask; task.CurrPointNo = emptyPalletEquip.AgvPositionCode; task.EndPointNo = "3DeliverSmallGoodsPoint"; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "3#车间从色粉存放点补充小托盘任务"; task.PalletInfoCode = emptyPalletEquip.ContainerCode; sqlSugarClient.AsTenant().BeginTran(); try { int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); //锁住开始色粉库位 emptyPalletEquip.EquipStatus = 1; sqlSugarClient.Updateable(emptyPalletEquip).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"3#车间从色粉存放点补充小托盘任务生成提交事务异常{ex.Message}"); } _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); return; } else //从2#缓存链条线生成补充空托盘任务 { if (workShop2Plc == null || !workShop2Plc.IsConnected) { _logger.Plc(DateTime.Now + "2#PLC未连接,请检查网络!"); return; } int work2EmptyAmount = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存链条线库存数")); int work2LineBusyFlag = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存空箱线体状态")); if (work2EmptyAmount > 0 && work2LineBusyFlag == 0) { //防止抢占其他任务节奏 Thread.Sleep(1000); work2LineBusyFlag = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存空箱线体状态")); work2EmptyAmount = workShop2Plc.readInt16ByAddress(StaticData.GetPlcAddress("2#缓存链条线库存数")); if (work2EmptyAmount > 0 && work2LineBusyFlag == 0) { bool hasTonerTask = sqlSugarClient.Queryable().Any(x => x.TaskType == StaticTaskType.DeliverTonerTask && x.TaskStatus < 5); if (hasTask) { //如果有agv等着接色粉,暂时不生成补充空托盘任务 return; } workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#缓存空箱线体状态"), 1); WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.SupplySmallPalletTask; task.CurrPointNo = "2DeliverMetrologyRoomPoint"; task.EndPointNo = "3DeliverSmallGoodsPoint"; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = " 3#车间从2#接驳位补充小托盘任务"; sqlSugarClient.AsTenant().BeginTran(); try { int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"3#车间从2#接驳位补充小托盘任务生成提交事务异常{ex.Message}"); workShop2Plc.writeInt16ByAddress(StaticData.GetPlcAddress("2#线体忙碌状态"), 0); } _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); return; } } } } catch (Exception ex) { _logger.Error($"CreateSupplySmallPalletToWorkshop3Task异常{ex.Message}"); } } /// /// 从2#接驳位到3#接驳位补小空箱任务 :3#车间补小空箱流程 /// private void CreateSupplementSmallPalletTask() { try { //判断是否有该任务 bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.SupplySmallPalletTask && it.TaskStatus < 5); if (hasTask) { _logger.Info("Agv已有2#接驳位到3#接驳位补小空箱任务"); return; } //寻找可用agv //WcsBaseEquip? agvEquip = GetCanUseAgv(); //if (agvEquip == null) //{ // _logger.Info("暂时没有可用agv"); // return; //} //起点库位 3#车间小料箱取送货接驳点 WcsBaseEquip startEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "2DeliverMetrologyRoomPoint"); //终点库位 2#车间计量室接驳点 WcsBaseEquip endEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "3DeliverSmallGoodsPoint"); sqlSugarClient.AsTenant().BeginTran(); WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.SupplySmallPalletTask; task.CurrPointNo = startEquip.AgvPositionCode; // task.NextPointNo = agvEquip.AgvPositionCode; task.EndPointNo = endEquip.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "2#接驳位到3#接驳位补小空箱任务"; int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; startEquip.EquipStatus = 1; endEquip.EquipStatus = 1; sqlSugarClient.Updateable(startEquip).ExecuteCommand(); sqlSugarClient.Updateable(endEquip).ExecuteCommand(); sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"2#接驳位到3#接驳位补小空箱任务异常{ex.Message}"); } } /// /// 2#色粉派送至色粉存放点任务 /// private bool CreateDeliverTonerTask(string rfid) { bool createResult = false; try { //判断是否有该任务 bool hasTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.DeliverTonerTask && it.PalletInfoCode == rfid); if (hasTask) { _logger.Info($"Agv已有托盘:{rfid}2#色粉派送至色粉存放点任务"); return true; } //起点库位 2#计量室车间小料箱取送货接驳点 WcsBaseEquip startEquip = sqlSugarClient.Queryable().First(it => it.EquipNo == "2DeliverMetrologyRoomPoint"); //终点库位 2#返程色粉人工拿取点 WcsBaseEquip? endEquip = sqlSugarClient.Queryable().Where(it => it.EquipStatus == 0 && it.EquipType == 7 && string.IsNullOrEmpty(it.ContainerCode)).OrderBy(x => x.Id).First(); if (endEquip == null) { //todo推送报警 _logger.Error("暂时没有可用色粉存放点库位"); return false; } sqlSugarClient.AsTenant().BeginTran(); try { WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.DeliverTonerTask; task.CurrPointNo = startEquip.AgvPositionCode; task.EndPointNo = endEquip.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "2#色粉派送至色粉存放点任务"; task.PalletInfoCode = rfid; int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; startEquip.EquipStatus = 1; endEquip.EquipStatus = 1; sqlSugarClient.Updateable(startEquip).ExecuteCommand(); sqlSugarClient.Updateable(endEquip).ExecuteCommand(); sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); createResult = true; } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"2#色粉派送至色粉存放点任务提交事务异常{ex.Message}"); } } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); _logger.Error($"生成2#色粉派送至色粉存放点并空箱送回2#接驳位任务异常{ex.Message}"); } return createResult; } #endregion 任务流程 #region 辅助方法 /// /// 判断是否还有色粉在连廊输送线或者没在色粉库位 /// /// private bool HasAnyTonerInLine() { try { // 色粉料箱 List tonerPallets = sqlSugarClient.Queryable().Where(x => x.TonerFlag == 1 && x.Amount > 0).ToList(); // 色粉库位的料箱码 List equipPalletInfos = sqlSugarClient.Queryable().Where(x => x.EquipType == 7 && !string.IsNullOrEmpty(x.ContainerCode)).ToList(); // 获取 tonerPallets 中的所有 PalletInfoCode var tonerPalletCodes = tonerPallets.Select(x => x.PalletInfoCode).ToList(); // 获取 equipPalletInfos 中的所有 ContainerCode var equipPalletCodes = equipPalletInfos.Select(x => x.ContainerCode).ToList(); // 检查是否有 tonerPalletCodes 不在 equipPalletCodes 中 bool result = tonerPalletCodes.Any(code => !equipPalletCodes.Contains(code)); return result; } catch (Exception ex) { return false; } } ///// ///// 从12号机台获取空托盘,返回库位信息 ///// ///// ///// //private async Task GetEmptyContainerByMachine12Async(string rfidKey) //{ // try // { // bool flag1 = await ReadSignalByRfidKeyAsync(rfidKey); // if (flag1) // { // string code = await ReadEpcStrByRfidKeyAsync(rfidKey); // if (!string.IsNullOrEmpty(code)) // { // // 通过该料箱是否绑定有物料来判断是否为空托盘 // bool hasMaterial = await sqlSugarClient.Queryable().AnyAsync(it => it.PalletInfoCode == code); // if (!hasMaterial) // { // WmsBaseLocation? location = await sqlSugarClient.Queryable().FirstAsync(it => it.EquipKey == rfidKey); // return location; // } // } // } // //_logger.Error($"12号机台库位{rfidKey}无空托盘"); // return null; // } // catch (Exception ex) // { // return null; // } //} /// /// 根据机台号寻找终点库位、判断机台的两个库位是否有空位置、没有的话先生成移库任务 /// machineId为该料箱目的地机台号 /// /// /// private WmsBaseLocation? GetTargetLocation(string machineCode, List AllWmsBaseLocationList) { try { bool hasMoveTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.MoveLocationTask && it.TaskStatus < 3); if (hasMoveTask) { _logger.Info($"目标库位无空位置,正在执行移库任务,暂时不生成送料任务,请等待...."); return null; } WmsBaseLocation? targetLocation; //移库起点终点 WmsBaseLocation? moveStartLocation; WmsBaseLocation? moveEndLocation; int machineId = StaticData.WmsMachineInfos.First(x => x.MachineCode == machineCode).MachineId; if (machineId >= 12 && machineId <= 16) { //12 - 16号机台都送往12号机台 machineId = 12; } //12号机台读RFID判断 //if (machineId >= 12) //{ // //光电信号 // bool flag1 = await ReadSignalByRfidKeyAsync("12-1"); // bool flag2 = await ReadSignalByRfidKeyAsync("12-2"); // if (!flag1) // { //12-1有空位 // targetLocation = AllWmsBaseLocationList.First(it => it.EquipKey == "12-1" && it.LocationStatus == 1); // return targetLocation; // } // //if (!flag2) //12-2有空位 // { // //默认全送到12-2库位,如果有料箱,agv送过去停着,人工取走库位上的箱子 // targetLocation = AllWmsBaseLocationList.First(it => it.EquipKey == "12-2" && it.LocationStatus == 1); // return targetLocation; // } // // 后期考虑优化,12号机台暂不考虑移库,因为库位距离其他机台比较远 //} //else if (machineId >= 1 && machineId <= 11) { targetLocation = AllWmsBaseLocationList.FirstOrDefault(it => it.MachineId == machineId && it.LocationStatus == 0 && string.IsNullOrEmpty(it.ContainerCode)); if (targetLocation != null) return targetLocation; //目标机台两个都有料箱,判断是否有机台里面的料箱是空的,有空箱可生成移库任务,否则等待 String sql = $"SELECT wbl.* FROM wms_base_location wbl join wms_pallet_info wpi on wbl.container_code = wpi.pallet_info_code where wbl.container_code is not null and wbl.container_code!='' and wbl.location_status=0 and wbl.machineid={machineId} and wpi.amount=0"; moveStartLocation = sqlSugarClient.SqlQueryable(sql).First(); if (moveStartLocation == null) { return null; // todo推送预警 // 目标机台没有空库位,没有可移库的空箱,等待 } #region 如果有补空箱任务,并且起点是要送料机台的库位,就不再生成移库任务 //目标机台的两个库位编号 List locationCodes = AllWmsBaseLocationList.Where(x => x.MachineId == machineId).Select(x => x.AgvPositionCode).ToList(); bool hasTask = sqlSugarClient.Queryable().Any(x => x.TaskType == StaticTaskType.SupplyEmptyPalletTask && locationCodes.Contains(x.CurrPointNo)); if (hasTask) { return null; } #endregion 如果有补空箱任务,并且起点是要送料机台的库位,就不再生成移库任务 //需要生成从该库位到其他机台的移库任务,找寻移库终点库位 moveEndLocation = AllWmsBaseLocationList.LastOrDefault(x => x.LocationId != moveStartLocation.LocationId && x.LocationStatus == 0 && string.IsNullOrEmpty(x.ContainerCode) && x.LocationId<=20); if (moveEndLocation == null) { // 没有可以移库的库位,请等待 return null; // todo:推送预警 } #region 如果有送料任务,并且终点是要送料机台的库位,就不再生成移库任务 bool hasSendTask = sqlSugarClient.Queryable().Any(it => it.TaskType == StaticTaskType.TransferMaterialBoxTask && it.EndPointNo == moveEndLocation.AgvPositionCode); if (hasSendTask) { //_logger.Info("Agv已有该库位的送料任务"); return null; } #endregion 如果有送料任务,并且终点是要送料机台的库位,就不再生成移库任务 else //生成移库任务 { //二次确认寻找可用agv,避免在这期间agv被其他线程占用 try { //WcsBaseEquip? agvEquip = GetCanUseAgv(); //if (agvEquip == null) //{ // _logger.Info("暂时没有可用agv"); // return null; //} WcsTask task = new WcsTask(); task.TaskType = StaticTaskType.MoveLocationTask; task.CurrPointNo = moveStartLocation.AgvPositionCode; task.EndPointNo = moveEndLocation.AgvPositionCode; task.TaskStatus = 0; task.CreatedTime = DateTime.Now; task.CreatedBy = "wcs"; task.TaskName = "1-12机台之间空托盘移库任务"; task.PalletInfoCode = moveStartLocation.ContainerCode; sqlSugarClient.AsTenant().BeginTran(); try { int id = sqlSugarClient.Insertable(task).ExecuteReturnIdentity(); WcsTaskLog wcsTaskLog = CoreMapper.Map(task); wcsTaskLog.Id = id; //锁定库位 moveStartLocation.LocationStatus = 1; moveEndLocation.LocationStatus = 1; sqlSugarClient.Updateable(moveStartLocation).ExecuteCommand(); sqlSugarClient.Updateable(moveEndLocation).ExecuteCommand(); sqlSugarClient.Insertable(wcsTaskLog).ExecuteCommand(); sqlSugarClient.AsTenant().CommitTran(); _logger.Agv($"生成{task.TaskName},起点:{task.CurrPointNo},终点:{task.EndPointNo}"); } catch (Exception ex) { _logger.Error($"生成移库任务提交事务异常:{ex.Message}"); sqlSugarClient.AsTenant().RollbackTran(); } } catch (Exception ex) { _logger.Error($"生成移库任务异常:{ex.Message}"); return null; } } } return null; } catch (Exception ex) { _logger.Error($"GetTargetLocationAsync方法异常:{ex.StackTrace}"); return null; } } #endregion 辅助方法 #region 测试方法 private async void test() { // 读RFID条码 // string code = await ReadEpcStrByRfidKeyAsync("1"); //读光电信号 //bool flag = await ReadSignalByRfidKeyAsync("1"); //bool flag1 = await ReadSignalByRfidKeyAsync("1"); //testTransitional(); //testTransitionalRollback(); } /// /// 测多线程事务影响程度 /// private void testTransitional() { Task.Run(() => { try { sqlSugarClient.AsTenant().BeginTran(); for (int i = 0; i < 10; i++) { Console.WriteLine($"线程1{i}"); //WmsStock stock = new WmsStock(); // stock.WorkshopId = i; // sqlSugarClient.Insertable(stock).ExecuteCommand(); Thread.Sleep(1000); } sqlSugarClient.AsTenant().CommitTran(); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); } }); Task.Run(() => { try { sqlSugarClient.AsTenant().BeginTran(); for (int i = 20; i < 30; i++) { //Console.WriteLine($"线程2{i}"); //WmsStock stock = new WmsStock(); //stock.WorkshopId = i; //sqlSugarClient.Insertable(stock).ExecuteCommand(); //Thread.Sleep(1000); //if (i == 25) //{ // Console.WriteLine($"事务回滚"); // throw new Exception("事务回滚"); //} } sqlSugarClient.AsTenant().CommitTran(); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); } }); } /// /// 测事务未开启但回滚 /// private void testTransitionalRollback() { try { throw new Exception("事务回滚"); sqlSugarClient.AsTenant().BeginTran(); for (int i = 0; i < 10; i++) { //Console.WriteLine($"线程1{i}"); //WmsStock stock = new WmsStock(); //stock.WorkshopId = i; //sqlSugarClient.Insertable(stock).ExecuteCommand(); //Thread.Sleep(1000); } sqlSugarClient.AsTenant().CommitTran(); } catch (Exception ex) { sqlSugarClient.AsTenant().RollbackTran(); } } #endregion 测试方法 } }