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

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.

# 任务驱动的任务调度方案
## 一、核心思路
```
不是一次性下发全部步骤,也不是等待接驳位信号
任务创建后 (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等待当前线程结束后标记停止