using System;using System.Collections.Generic;using System.Linq;using System.Threading;using System.Threading.Tasks;
// --- 数据结构定义 ---
public enum CargoStatus{ AtOrigin, WaitingForDispatch, // 在起点或缓冲区等待调度指令 EnRoute, ArrivedAtBay, Loaded}
public enum LoadingBayStatus{ Idle, WaitingForItem, // 等待下一个序列的货物 ItemArriving, // 货物正在进入 ItemPresent, // 货物已到达,等待叉车 ForkliftOperating // 叉车正在作业}
// 货物信息public class CargoItem{ public string Id { get; set; } public string OriginLocation { get; set; } // 简化为字符串 public string DestinationCity { get; set; } public int DestinationSequence { get; set; } // 目的地在路线中的序号 (广州=1, 佛山=2, 广西=3) public string TruckLoadOrderId { get; set; } public CargoStatus Status { get; set; } = CargoStatus.AtOrigin;
public override string ToString() => $"货物 {Id} (去往: {DestinationCity}, 顺序: {DestinationSequence})";}
// 路线停靠点public class RouteStop{ public string City { get; set; } public int Sequence { get; set; } // 1: 广州, 2: 佛山, 3: 广西}
// 出货口public class LoadingBay{ public string Id { get; set; } public LoadingBayStatus Status { get; set; } = LoadingBayStatus.Idle; public string HandlingOrderId { get; set; } = null; public string ExpectedItemId { get; set; } = null; // 当前等待的货物ID private readonly SemaphoreSlim _accessSemaphore = new SemaphoreSlim(1, 1); // 控制对出货口最终导轨的访问
// 模拟货物到达 public async Task<bool> TryOccupyForArrival(string itemId, string orderId) { if (!await _accessSemaphore.WaitAsync(0)) // 尝试立即获取锁,0表示不等待 { Console.WriteLine($"出货口 {Id} 忙碌,无法接收货物 {itemId}。"); return false; // 如果已被占用,则无法进入 } // 获取到锁 Status = LoadingBayStatus.ItemArriving; HandlingOrderId = orderId; ExpectedItemId = itemId; // 明确是哪个货物正在进入 Console.WriteLine($"出货口 {Id} 已锁定,准备接收货物 {itemId} (订单: {orderId})。"); return true; }
// 货物完全到达 public void ItemArrived(string itemId) { if (ExpectedItemId == itemId) { Status = LoadingBayStatus.ItemPresent; Console.WriteLine($"货物 {itemId} 已到达出货口 {Id},等待叉车。"); } else { Console.WriteLine($"错误:到达出货口 {Id} 的货物 {itemId} 不是预期的 {ExpectedItemId}!"); // 可能需要错误处理逻辑 Release(); // 释放锁 } }
// 叉车完成搬运,释放出货口 public void Release() { Status = LoadingBayStatus.Idle; Console.WriteLine($"出货口 {Id} 已空闲。"); ExpectedItemId = null; HandlingOrderId = null; _accessSemaphore.Release(); // 释放锁 }}
// 单个卡车的装货订单public class TruckLoadOrder{ public string OrderId { get; set; } public List<RouteStop> Route { get; set; } public List<CargoItem> Items { get; set; } public string AssignedLoadingBayId { get; set; } public List<string> TargetDeliverySequence { get; private set; } // 按目的地顺序排序的货物ID private int _currentIndex = 0;
// 计算目标出库序列 public void CalculateSequence() { TargetDeliverySequence = Items .OrderBy(item => item.DestinationSequence) // 按目的地序号升序排序 .Select(item => item.Id) .ToList(); }
public string GetNextItemId() { if (_currentIndex < TargetDeliverySequence.Count) { return TargetDeliverySequence[_currentIndex]; } return null; // 所有货物已处理 }
public void ItemDispatched() { _currentIndex++; }
public bool IsComplete() => _currentIndex >= TargetDeliverySequence.Count;}
// --- 模拟控制器 ---public class WarehouseController{ private readonly Dictionary<string, LoadingBay> _loadingBays; private readonly Dictionary<string, CargoItem> _allCargoItems; // 模拟WMS中的货物信息 private readonly Queue<TruckLoadOrder> _orderQueue = new Queue<TruckLoadOrder>();
public WarehouseController(List<LoadingBay> bays, List<CargoItem> items) { _loadingBays = bays.ToDictionary(b => b.Id); _allCargoItems = items.ToDictionary(i => i.Id); // 将货物与其订单关联 (简化处理,假设所有货物属于一个订单) var orderId = "ORDER_SZ_GX"; var route = new List<RouteStop> { new RouteStop { City = "广州", Sequence = 1 }, new RouteStop { City = "佛山", Sequence = 2 }, new RouteStop { City = "广西", Sequence = 3 } }; foreach (var item in items) { item.TruckLoadOrderId = orderId; var stop = route.First(r => r.City == item.DestinationCity); item.DestinationSequence = stop.Sequence; } var truckOrder = new TruckLoadOrder { OrderId = orderId, Route = route, Items = items, AssignedLoadingBayId = bays.First().Id // 分配到第一个出货口 }; truckOrder.CalculateSequence(); _orderQueue.Enqueue(truckOrder); }
public async Task RunSimulation() { Console.WriteLine("启动仓库调度模拟...");
while (_orderQueue.Count > 0) { var currentOrder = _orderQueue.Peek(); // 查看下一个订单,但不移除 var bay = _loadingBays[currentOrder.AssignedLoadingBayId];
if (currentOrder.IsComplete()) { Console.WriteLine($"订单 {currentOrder.OrderId} 已完成装车。"); _orderQueue.Dequeue(); // 完成,处理下一个订单 continue; }
// 检查出货口是否空闲,可以接收下一个货物 if (bay.Status == LoadingBayStatus.Idle) { string nextItemId = currentOrder.GetNextItemId(); if (nextItemId != null) { CargoItem itemToDispatch = _allCargoItems[nextItemId];
// 关键:尝试占用出货口,只有成功了才真正调度货物 if (await bay.TryOccupyForArrival(itemToDispatch.Id, currentOrder.OrderId)) { // 占用成功,标记货物已调度,并模拟运输 currentOrder.ItemDispatched(); // 移到下一个 Console.WriteLine($"控制器: 批准调度 {itemToDispatch} 到出货口 {bay.Id}"); itemToDispatch.Status = CargoStatus.WaitingForDispatch; // 更新状态
// 启动一个异步任务来模拟货物运输和处理 _ = Task.Run(async () => await SimulateItemTransportAndHandling(itemToDispatch, bay)); } else { // 出货口忙,等待下次循环检查 Console.WriteLine($"控制器: 出货口 {bay.Id} 忙碌,暂时无法调度 {itemToDispatch}。"); await Task.Delay(500); // 等待一会再试 } } } else { // 出货口不空闲,等待 // Console.WriteLine($"控制器: 等待出货口 {bay.Id} 空闲..."); await Task.Delay(1000); // 等待出货口处理完成 } }
Console.WriteLine("所有订单处理完毕,模拟结束。"); }
// 模拟单个货物的运输和叉车搬运 private async Task SimulateItemTransportAndHandling(CargoItem item, LoadingBay bay) { Console.WriteLine($"导轨系统: 开始运输 {item} 从 {item.OriginLocation} 到 {bay.Id}..."); item.Status = CargoStatus.EnRoute; await Task.Delay(TimeSpan.FromSeconds(GetRandomDuration(2, 5))); // 模拟运输时间
// 货物到达出货口 item.Status = CargoStatus.ArrivedAtBay; bay.ItemArrived(item.Id); // 通知出货口货物已在门口
// 模拟叉车作业 if (bay.Status == LoadingBayStatus.ItemPresent) { Console.WriteLine($"叉车: 开始搬运 {item} 从出货口 {bay.Id}..."); bay.Status = LoadingBayStatus.ForkliftOperating; await Task.Delay(TimeSpan.FromSeconds(GetRandomDuration(3, 6))); // 模拟叉车搬运时间 item.Status = CargoStatus.Loaded; Console.WriteLine($"叉车: 完成搬运 {item}。"); bay.Release(); // 释放出货口,允许下一个货物进入 } }
private Random _random = new Random(); private int GetRandomDuration(int minSeconds, int maxSeconds) { return _random.Next(minSeconds, maxSeconds + 1); }}
// --- 主程序 ---public class Program{ public static async Task Main(string[] args) { Console.OutputEncoding = System.Text.Encoding.UTF8;
// 1. 初始化仓库元素 var loadingBays = new List<LoadingBay> { new LoadingBay { Id = "Bay-01" } // 可以添加更多出货口 };
var cargoItems = new List<CargoItem> { // 注意:Id 唯一即可,OriginLocation 仅为示例 new CargoItem { Id = "GZ-001", OriginLocation = "Area A", DestinationCity = "广州" }, new CargoItem { Id = "FS-001", OriginLocation = "Area B", DestinationCity = "佛山" }, new CargoItem { Id = "GX-001", OriginLocation = "Area C", DestinationCity = "广西" }, new CargoItem { Id = "GZ-002", OriginLocation = "Area D", DestinationCity = "广州" }, new CargoItem { Id = "FS-002", OriginLocation = "Area E", DestinationCity = "佛山" }, new CargoItem { Id = "GX-002", OriginLocation = "Area F", DestinationCity = "广西" }, new CargoItem { Id = "GZ-003", OriginLocation = "Area A", DestinationCity = "广州" } };
// 2. 创建并运行控制器 var controller = new WarehouseController(loadingBays, cargoItems); await controller.RunSimulation();
Console.WriteLine("按任意键退出..."); Console.ReadKey(); }}
评论