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使用错误:
错误的等待API:Lely CANopen纤程模型中,
Wait()是阻塞式等待,会卡住当前线程导致无法切换到其他纤程;而Await()才是专门用于纤程中等待异步操作并主动让出执行权的方法。不必要的类型包装:代码中
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
相关产品推荐
相关产品推荐

