You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Lely CANopen中AsyncWait未异步执行?求错误排查方案

问题

使用Lely CANopen栈的纤程(Fiber)执行不同速率任务时,TaskA(1秒间隔)和TaskB(500毫秒间隔)未按预期交替输出,实际仅持续输出TaskA内容,Wait(AsyncWait(d))似乎未让出执行权。

示例代码:

class MyDriver : public canopen::FiberDriver {
 public:
  using FiberDriver::FiberDriver;

 private:
  // Configure device
  void OnConfig(std::function<void(std::error_code ec)> res) noexcept override {
    try {
      // Do some SDO configuration

      // Schedule tasks
      Defer(&MyDriver::TaskA, this);
      Defer(&MyDriver::TaskB, this);

      // Return no error
      res({});
    } catch (canopen::SdoError& e) {
      res(e.code());
    }
  }

  void TaskA() noexcept {
    while (true) {
      // Do some processing
      std::cout << "Hello from task A" << std::endl;

      // Wait
      Wait(AsyncWait(duration(std::chrono::milliseconds(1000))));
    }
  }

  void TaskB() noexcept {
    while (true) {
      // Do some processing
      std::cout << "Hello from task B" << std::endl;

      // Wait
      Wait(AsyncWait(duration(std::chrono::milliseconds(500))));
    }
  }

};

int main() {
  // A lot of set up omitted for clarity
  // Create context, event loop, CAN channel, etc.

  // Create master
  canopen::AsyncMaster master(timer, chan, "../config/master.dcf", "", 1);

  // Start NMT service by pretending to get a reset command
  master.Reset();

  // Create a driver for CAN device
  MyDriver driver(exec, master, 2);

  // Run the event loop
  loop.run();

  return 0;
}

预期输出:

Hello from task A
Hello from task B
Hello from task B
Hello from task A
Hello from task B
Hello from task B
...

实际输出:

Hello from task A
Hello from task A
Hello from task A
Hello from task A
...
解决方案

问题核心在于纤程调度逻辑和API使用错误:

  1. 错误的等待API:Lely CANopen纤程模型中,Wait()是阻塞式等待,会卡住当前线程导致无法切换到其他纤程;而Await()才是专门用于纤程中等待异步操作并主动让出执行权的方法。

  2. 不必要的类型包装:代码中duration(std::chrono::milliseconds(...))属于冗余包装,会导致类型不匹配,影响定时器事件的正确触发。

修改后的任务代码:

void TaskA() noexcept {
  while (true) {
    std::cout << "Hello from task A" << std::endl;
    // 使用Await替代Wait,直接传入标准chrono时长
    Await(AsyncWait(std::chrono::milliseconds(1000)));
  }
}

void TaskB() noexcept {
  while (true) {
    std::cout << "Hello from task B" << std::endl;
    Await(AsyncWait(std::chrono::milliseconds(500)));
  }
}

额外检查点:

  • 确认exec是canopen::FiberExecutor类型,且已正确关联到事件循环loop,否则纤程切换逻辑无法生效。
  • 验证OnConfig方法确实被调用(可添加日志),确保TaskA和TaskB被成功调度。

内容的提问来源于stack exchange,提问作者Jacob

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 07:40:29