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

5.3 KiB

任务驱动的任务调度方案

一、核心思路

不是一次性下发全部步骤,也不是等待接驳位信号

任务创建后 (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 即时

提升机并发控制

// 从 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等待当前线程结束后标记停止