You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
wcs_core/任务执行调度-当前实现记录.md

229 lines
7.1 KiB
Markdown

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

# 任务执行调度 — 当前实现记录
> 记录时间2026-06-13
> 状态:包材入库 (category=1, type=1) 任务驱动并行执行已跑通
---
## 一、整体架构
```
UI (SystemMonitorView)
├─ [▶ 启动] / [■ 停止] 包材入库调度
└─ SystemMonitorViewModel
└─ MaterialInStoreExecutor (Singleton)
Sln.Wcs.Strategy / MaterialInStoreExecutor
├─ 轮询待执行任务 (每 5 秒)
├─ 多任务并行 (Thread最多 10 个)
├─ 单任务内串行 (逐条 detail)
└─ 设备下发 (AGV/提升机/输送线)
Sln.Wcs.Business / TaskCreateService
└─ 拓扑路由 → 自动生成 LiveTaskQueue + List<LiveTaskDetail>
```
## 二、任务创建
### 输入
| 参数 | 说明 | 示例 |
|------|------|------|
| startBuilding | 起始楼栋 | 13 |
| startFloor | 起始楼层 | 1 |
| startLocation | 起始位置号 | 101 |
| endBuilding | 目标楼栋 | 15 |
| endFloor | 目标楼层 | 3 |
| endLocation | 目标位置号 | 102 |
| taskType | 1入库 / 2出库 | 1 |
| taskCategory | 1包材 / 2成品 / 3托盘 | 1 |
| palletBarcode | 托盘条码 | PALLET001 |
| materialCode | 物料编码 | M001 |
### 输出
```
LiveTaskQueue
├─ taskCode: 自动生成 (yyyyMMddHHmmss + 随机数)
├─ taskType, taskCategory
├─ startPoint, endPoint: 自动拼接为 {building}#_L{floor}_{location}
├─ taskStatus: 1 (待执行)
├─ taskSteps: 明细数量
└─ taskDetails: List<LiveTaskDetail>
```
### 拓扑规则
- 所有楼栋 13# / 14# / 15# 均为 1~5F
- 每栋楼有 1 台提升机,可直达任意楼层(全连接)
- 跨栋仅 2F 连通:
- (13,2) ↔ (14,2):廊桥交接,两段 AGV13# AGV → BRIDGE_13_1414# AGV 从 BRIDGE_13_14 接走)
- (14,2) ↔ (15,2)14# AGV 可驶入 15#,不生成过渡段
### 示例13栋1楼101 → 15栋3楼102
```
路由节点: (13,1) → (13,2) → (14,2) → (15,2) → (15,3)
Detail 1: AGV 13#_L1_101 → 13#_L1_HOIST
Detail 2: 提升机 13#_L1_HOIST → 13#_L2_HOIST
Detail 3: AGV 13#_L2_HOIST → BRIDGE_13_14 (13# AGV)
Detail 4: AGV BRIDGE_13_14 → 15#_L2_HOIST (14# AGV 直达)
Detail 5: 提升机 15#_L2_HOIST → 15#_L3_HOIST
Detail 6: AGV 15#_L3_HOIST → 15#_L3_102
```
## 三、任务执行
### 执行器MaterialInStoreExecutor
**位置**`Sln.Wcs.Strategy/MaterialInStoreExecutor.cs`
**查询条件**
```csharp
taskType == 1 && taskCategory == 1 && taskStatus == 1
```
**轮询间隔**5 秒
### 主循环
```
Start()
└─ Task.Run → RunLoopAsync
└─ while (!cancelled):
ExecuteAsync() ← 阻塞等待所有任务线程完成
await Task.Delay(5000)
```
### 并行策略
```
ExecuteAsync:
查询所有待执行任务
→ foreach task → new Thread:
TaskSemaphore.Wait() ← 最多 10 线程
ProcessOneAsync(task).GetAwaiter().GetResult()
TaskSemaphore.Release()
→ Thread.Join() 等待全部完成
```
### 单任务处理
```
ProcessOneAsync(task):
🔒 lock → taskStatus = 2, Update(task)
foreach detail (按 objId 排序):
if detail 已完成 → continue
🔒 lock → detailStatus = 2, Update(detail)
🔓
下发设备 (根据 deviceType):
1 → DispatchAgvAsync (10s 模拟延迟)
2 → DispatchHoistAsync (20s 模拟延迟,按楼栋限 2 并发)
0 → DispatchConveyorAsync
🔒 lock → detailStatus = 3, Update(detail)
🔓
🔒 lock → taskStatus = 3, Update(task)
```
### 并发控制
| 控制点 | 机制 | 值 |
|--------|------|-----|
| 任务级并发 | `SemaphoreSlim` | 最多 10 个 |
| 提升机并发 | `ConcurrentDictionary<int, SemaphoreSlim>` | 每栋楼 2 台 |
| AGV 并发 | 不限 | — |
| DB 写入 | `lock (DbWriteLock)` 串行化 | — |
| 启停状态 | `lock (_lock)` + `volatile bool` | — |
### 线程安全
- **启停**`lock (_lock)` 保护 `_cts` / `_isRunning`
- **DB 写入**`lock (DbWriteLock)` 保护 SqlSugar UpdateContext 为单例,多线程写入冲突)
- **提升机信号量**`ConcurrentDictionary` 线程安全
- **任务信号量**`SemaphoreSlim` 本身线程安全
- **延迟模拟**`await Task.Delay` 在锁外,多任务并行不受影响
## 四、仓储线程安全
**位置**`Sln.Wcs.Repository/Repository.cs`
```csharp
public Repository(ISqlSugarClient db)
{
itenant = db.AsTenant();
Context = (SqlSugarClient)db; // 直接用 SqlSugarScope内部管理连接池
}
```
`SqlSugarScope` 注册为 Singleton通过 `[Tenant]` 特性自动路由数据库。
## 五、设备下发(当前为模拟)
| 设备 | 方法 | 延迟 | 并发限制 |
|------|------|------|---------|
| AGV | `DispatchAgvAsync` | 10 秒 | 无 |
| 提升机 | `DispatchHoistAsync` | 20 秒 | 每栋楼 2 台 |
| 输送线 | `DispatchConveyorAsync` | 无 | 无 |
后续对接AGV → `HikRoBotDispatchHub.ReciveTask`,提升机 → `HoistDispatchHub.TaskDispatch`
## 六、UI 控制
**系统监控页面** — 顶部卡片:
```
┌──────────────────────────────────────────────┐
│ ● 包材入库调度 运行中 [▶ 启动] [■ 停止] │
└──────────────────────────────────────────────┘
```
按钮绑定:
- 启动 → `MaterialInStoreExecutor.Start()`
- 停止 → `MaterialInStoreExecutor.Stop()`
- 状态指示灯:绿色 = 运行中,红色 = 已停止
## 七、DI 注册
**App.axaml.cs**
```csharp
// Assembly 扫描
Assembly.LoadFrom("Sln.Wcs.Strategy.dll")
// Singleton 注册
services.AddSingleton<MaterialInStoreExecutor>();
```
**依赖关系**
```
MaterialInStoreExecutor (Singleton)
├─ SerilogHelper (Singleton)
├─ ILiveTaskQueueService (Transient, 来自 Scrutor 扫描)
└─ ILiveTaskDetailService (Transient, 来自 Scrutor 扫描)
```
## 八、关键文件
| 文件 | 说明 |
|------|------|
| `Sln.Wcs.Business/TaskCreateService.cs` | 拓扑路由 + 任务创建 |
| `Sln.Wcs.Strategy/MaterialInStoreExecutor.cs` | 包材入库执行器 |
| `Sln.Wcs.Repository/Repository.cs` | 仓储基类(线程安全改造) |
| `Sln.Wcs.UI/ViewModels/SystemMonitorViewModel.cs` | 系统监控 VM启停控制 |
| `Sln.Wcs.UI/Views/SystemMonitorView.axaml` | 系统监控页面 |
| `Sln.Wcs.UI/App.axaml.cs` | DI 注册 |
| `接驳位驱动调度方案.md` | 调度方案设计文档 |
## 九、待优化项
1. **真实设备对接**:替换 `DispatchAgvAsync` / `DispatchHoistAsync` 中的模拟延迟为实际 API 调用
2. **扩展其他类型**:成品入库/出库、托盘入库/出库等(参考 MaterialInStoreExecutor 模板)
3. **DB 写入优化**:去掉 `lock (DbWriteLock)`,从根本上解决 SqlSugar 多线程写入问题(可能需要连接串配置 `Max Pool Size` 或改造仓储层)
4. **任务优先级**:当前 FIFO可按优先级排序
5. **异常恢复**:任务中途停止后重新启动的状态恢复
6. **手动触发**UI 上支持手动输入接驳位 + RFID 触发单条明细执行