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

171 lines
5.3 KiB
Markdown

# 任务驱动的任务调度方案
## 一、核心思路
```
不是一次性下发全部步骤,也不是等待接驳位信号
任务创建后 (status=1)
→ 执行器轮询到 → 启动线程
→ 单任务内逐条串行下发明细
→ 前一条完成 → 自动执行下一条
→ 全部完成 → 任务结束
多任务之间并行执行,互不干扰
```
## 二、执行流程
```
Start() 启动后台轮询
└─ RunLoopAsync (每 5 秒一轮)
└─ ExecuteAsync
├─ 查询 taskType=1, taskCategory=1, taskStatus=1
├─ foreach task → new Thread:
│ │
│ ├─ TaskSemaphore.Wait() ← 最多 10 线程
│ │
│ └─ ProcessOneAsync(task):
│ │
│ ├─ taskStatus → 2
│ │
│ ├─ foreach detail (按 objId):
│ │ │
│ │ ├─ detailStatus → 2
│ │ ├─ 下发设备
│ │ │ 1 → AGV (不限并发)
│ │ │ 2 → 提升机 (每栋限 2)
│ │ │ 0 → 输送线
│ │ ├─ 等待执行完成
│ │ └─ detailStatus → 3
│ │
│ └─ taskStatus → 3
└─ Thread.Join() 等本轮全部完成 → 5 秒后下一轮
```
## 三、并发模型
```
任务 A: Detail 1 → Detail 2 → Detail 3 → ...
任务 B: Detail 1 → Detail 2 → Detail 3 → ... 三个任务同时跑
任务 C: Detail 1 → Detail 2 → Detail 3 → ...
单任务内: 串行 (前一条完成才执行下一条)
多任务间: 并行 (各自独立线程)
```
### 限制
| 控制项 | 机制 | 值 |
|--------|------|-----|
| 最大并行任务数 | `SemaphoreSlim` | 10 |
| 提升机并行/栋 | `ConcurrentDictionary<int, SemaphoreSlim>` | 2 |
| AGV 并行 | 无限制 | — |
| DB 写入 | `lock (DbWriteLock)` | 串行 |
## 四、单任务处理详情
```
ProcessOneAsync(task):
Step 1 ─ 标记任务执行中
lock (DbWriteLock):
task.taskStatus = 2
Update(task)
Step 2 ─ 逐条处理明细 (按 objId 排序)
for each detail:
跳过已完成 (status 2 or 3)
lock (DbWriteLock):
detail.taskStatus = 2
Update(detail)
↓ 下发设备 (锁外,可并行)
deviceType:
1 → DispatchAgvAsync AGV 模拟 10s
2 → DispatchHoistAsync 提升机模拟 20s
0 → DispatchConveyorAsync 输送线
成功:
lock (DbWriteLock):
detail.taskStatus = 3
Update(detail)
失败:
lock (DbWriteLock):
detail.taskStatus = 1 回退待重试
Update(detail)
return (中断任务)
Step 3 ─ 标记任务完成
lock (DbWriteLock):
task.taskStatus = 3
Update(task)
```
## 五、设备下发
| 设备类型 | deviceType | 方法 | 模拟延迟 | 并发控制 |
|---------|-----------|------|---------|---------|
| AGV | 1 | `DispatchAgvAsync` | 10s | 无限制 |
| 提升机 | 2 | `DispatchHoistAsync` | 20s | 每栋 2 台 |
| 输送线 | 0 | `DispatchConveyorAsync` | 即时 | — |
### 提升机并发控制
```csharp
// 从 startPoint 提取楼栋号: "14#_L2_HOIST" → 14
var building = ExtractBuilding(detail.startPoint);
// 获取该楼栋信号量,首次自动创建 SemaphoreSlim(2, 2)
var semaphore = HoistSemaphores.GetOrAdd(building, _ => new SemaphoreSlim(2, 2));
await semaphore.WaitAsync(); // 等待有空闲提升机
// ... 执行 ...
semaphore.Release(); // 释放
```
## 六、执行示例
3 个包材入库任务,每个 6 条明细:
```
T+0s [线程1] 任务A Detail1 AGV开始 [线程2] 任务B Detail1 AGV开始 [线程3] 任务C Detail1 AGV开始
T+10s [线程1] 任务A Detail1 完成 [线程2] 任务B Detail1 完成 [线程3] 任务C Detail1 完成
T+10s [线程1] 任务A Detail2 提升机开始 [线程2] 任务B Detail2 提升机开始 [线程3] 等待(13#提升机满)
T+30s [线程1] 任务A Detail2 完成 [线程2] 任务B Detail2 完成 [线程3] 任务C Detail2 提升机开始
T+30s [线程1] 任务A Detail3 AGV开始 [线程2] 任务B Detail3 AGV开始
...并行继续...
```
## 七、状态流转
```
LiveTaskQueue.taskStatus:
1 (待执行) → 2 (执行中) → 3 (已完成)
LiveTaskDetail.taskStatus:
1 (待执行) → 2 (执行中) → 3 (已完成)
↘ 失败回退 → 1 (待重试)
```
## 八、UI 控制
系统监控页面顶部卡片,点击启动/停止:
```
┌──────────────────────────────────────────────────┐
│ ● 包材入库调度 运行中/已停止 [▶ 启动] [■ 停止] │
└──────────────────────────────────────────────────┘
```
- `Start()` → 创建 `CancellationTokenSource`,启动 `RunLoopAsync`
- `Stop()` → 取消 token等待当前线程结束后标记停止