我正在尝试使用Lely CANopen堆栈中的光纤执行一些任务。但是,我要么不理解模型,要么有什么东西坏了。我想做的是以不同的速率运行多个任务。
基于教程here的示例:
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
...
所以看起来Wait(AsyncWait(d))
实际上并没有产生执行。我做错了什么?
1条答案
按热度按时间bfrts1fy1#
(Answered here,但在下面重复,以便于查找。)
这是因为您使用
Defer()
而不是Post()
来排定任务的日程。Defer()
将任务提交给“strand”执行器。strand保证提交给它的任务永远不会并发运行。因此,它只会在任务A完成后执行任务B。这在多线程应用程序(例如使用LoopDriver
时)中非常有用,可以在不必使用互斥或其他显式同步机制的情况下防止争用情况。Defer()
可能不是最明显的名称。它最初来自Boost.Asio中的执行程序,表示提交的任务不会与执行提交的任务(在您的示例中为OnConfig()
)同时运行。在本例中,它的意思是“延迟任务A直到OnConfig()
完成,延迟任务B直到任务A完成”。