- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
在 Windows 上,我观察到如果 async_read
操作在串行端口上成功完成,我会立即启动另一个 async_read
操作来读取 n
字节,第二个 async_read
操作立即意外完成并成功传输 0 字节。
在第二次async_read
操作之后,如果发起第三次async_read
操作来读取n
字节,那么它将完成成功并传输了 n
个字节
// where buffer_size(buffer) and n are both greater than 1
async_read(serial, buffer, transfer_exactly(n), [](error, bytes_transferred) {
// completes with error=success and bytes_transferred=n
async_read(serial, buffer, transfer_exactly(n), [](error, bytes_transferred) {
// complete with error=success and bytes_transferred=0
async_read(serial, buffer, transfer_exactly(n), [](error, bytes_transferred) {
// completes with error=success and bytes_transferred=n
});
});
});
如果在第一个和第二个async_read
操作之间执行 1 毫秒休眠,则第二个操作将成功完成并传输 n
个字节
// where buffer_size(buffer) and n are both greater than 1
async_read(serial, buffer, transfer_exactly(n), [](error, bytes_transferred) {
// completes with error=success and bytes_transferred=n
sleep_for(milliseconds(1));
async_read(serial, buffer, transfer_exactly(n), [](error, bytes_transferred) {
// completes with error=success and bytes_transferred=n
});
});
为什么会发生这种情况,我该如何避免?
具体而言,我在 Windows 上使用 Boost.Asio 通过 ATXMEGA-192A3U 模拟的 RS232 与微 Controller 通信。我向 Controller 发送启动命令并读取超时的输出。我通过调用下面给出代码的 ReadPort
函数读取输出。该程序连续执行以下阅读任务:
R\r\n
n
个字节的输出,持续数百毫秒。步骤 2 中的 async_read
操作意外成功完成,尽管没有读取请求的字节数。
class BoostBasedCommunication
{
public:
BoostBasedCommunication();
~BoostBasedCommunication(void);
/*...*/
virtual int ReadPort(
int const numberOfCharacters, // maximum number of characters to be read
unsigned long const globalTimeout, // maximum time the operation is allowed to take in ms
unsigned long const intermediateTimeout, // maximum time allowed between two consequtive characters in ms
int& numberOfCharactersRead
);
/*...*/
private:
/*...*/
std::vector<unsigned char> inputBuffer; ///< buffer to save data to that is received
size_t numberOfBytesRead; ///< Number of bytes read
int lastErrorCode; ///< last error code
io_service my_io_service; ///< boost io service class
serial_port port; ///< boost serial port class
/*...*/
};
// Reads from the port until numberOfCharacters have been read, or the
// deadline_timer has expired, or the time between two consecutive calls of
// the completion condition is larger than intermediateTimeoutMS
int BoostBasedCommunication::ReadPort(
int const numberOfCharacters, // maximum number of characters to be read
unsigned long const globalTimeoutMS, // maximum time the operation is allowed to take in ms
unsigned long const intermediateTimeoutMS, // maximum time allowed between two consecutive characters in ms
int& numberOfCharactersRead // Actual number of characters read
)
{
try
{
OutputDebugStringA("ReadPort called\r\n");
my_io_service.reset();
deadline_timer gloabalTimeout(my_io_service);
inputBuffer.resize(numberOfCharacters);
timeoutHandler myGlobalTimeoutHandler(&port);
completion_handler_2 myHandler(&gloabalTimeout, numberOfBytesRead);
completion_condition_2 my_completion_condition(intermediateTimeoutMS, numberOfCharacters);
// Set the timer
gloabalTimeout.expires_from_now(boost::posix_time::milliseconds(globalTimeoutMS));
gloabalTimeout.async_wait(myGlobalTimeoutHandler);
async_read(port, boost::asio::buffer(inputBuffer, numberOfCharacters), my_completion_condition, myHandler);
my_io_service.run(); // run the io service
numberOfCharactersRead = numberOfBytesRead;
}
catch (std::exception&)
{
return COMMUNICATIONFAILED;
}
return NOERROR;
}
class completion_condition_2
{
public:
completion_condition_2(
long intermediateTimeOutTime,
size_t numberOfCharactersTobeRead
) :intermediateTimeOutTime(intermediateTimeOutTime),
numberOfCharactersTobeRead(numberOfCharactersTobeRead)
{}
std::size_t operator()(
const boost::system::error_code& error, // Result of latest async_read_some operation.
std::size_t bytes_transferred // Number of bytes transferred so far.
)
{
if (error)
{
OutputDebugStringA(("completion_condition received error code: " + error.message() + "\r\n").c_str());
if (error.value() == ERROR_OPERATION_ABORTED)
{
return 0;
}
}
/* ...Code concerning the intermediate timeout, which is commented out...*/
if (numberOfCharactersTobeRead <= bytes_transferred) // Enough data has been read
{
std::stringstream message;
message << "completion_condition: bytes transferred: " << bytes_transferred << " of " << numberOfCharactersTobeRead << " => done!" << std::endl;
OutputDebugStringA(message.str().c_str());
return 0;
}
else // More data should be read.
{
std::stringstream message;
message << "completion_condition: bytes transferred: " << bytes_transferred << " of " << numberOfCharactersTobeRead << " => continue!" << std::endl;
OutputDebugStringA(message.str().c_str());
return numberOfCharactersTobeRead - bytes_transferred;
}
}
private:
size_t numberOfCharactersTobeRead; ///< Number of characters to be read
};
class completion_handler_2 {
public:
completion_handler_2(
deadline_timer* _globalTimeout,
size_t& numberOfBytesRead
) :_globalTimeout(_globalTimeout),
numberOfBytesRead(numberOfBytesRead)
{
}
void operator()(
const boost::system::error_code& error, // Result of operation.
std::size_t bytes_transferred // Number of bytes read.
)
{
OutputDebugStringA(("completion handler called with error code: " + error.message() + "\r\n").c_str());
if (error)
{
if (error.value() == ERROR_OPERATION_ABORTED)
{
numberOfBytesRead = bytes_transferred;
return;
}
else
{
BOOST_THROW_EXCEPTION(std::exception("Communication failed"));
}
}
OutputDebugStringA("completion handler: timeout cancelation.\r\n");
_globalTimeout->cancel();
numberOfBytesRead = bytes_transferred;
}
private:
deadline_timer* _globalTimeout; ///< global timeout deadline timer
size_t& numberOfBytesRead; ///< number of bytes read
};
当我执行第一个按预期工作的读取时,我收到以下输出:
ReadPort called
completion_condition: bytes transferred: 0 of 3 => continue!
completion_condition: bytes transferred: 3 of 3 => done!
completion handler called with error code: success
completion handler timeout cancelation.
timeoutHandler received error code: The I/O operation has been aborted because of either a thread exit or an application request
如果我在第一次读取完成后立即执行另一次读取,则操作会在 2 毫秒后完成,并显示以下输出:
ReadPort called
completion_condition: bytes transferred: 0 of 1024 => continue!
completion handler called with error code: success // Why is the completion handler called here, although the completion condition did not return 0?
completion handler timeout cancelation.
timeoutHandler received error code: The I/O operation has been aborted because of either a thread exit or an application request
第三次读取,紧接着最后一次读取按预期工作:
ReadPort called
completion_condition: bytes transferred: 0 of 1024 => continue!
completion_condition: bytes transferred: 8 of 1024 => continue!
...
completion_condition: bytes transferred: 88 of 1024 => continue!
completion_condition: bytes transferred: 96 of 1024 => continue!
timeoutHandler called cancel of seriel port.
completion_condition received error code: The I/O operation has been aborted because of either a thread exit or an application request
completion handler called with error code: The I/O operation has been aborted because of either a thread exit or an application request
最佳答案
简而言之,根本问题是:
ReadFile
的解读带有超时的 API 契约(Contract)不正确ReadFile
API契约(Contract)最简单的解决方案是在应用程序代码中考虑这种行为,并发出另一个 async_read
如果前一个成功完成并读取 0 个字节,则执行操作。根据通信驱动程序的实现,读取之间 1 毫秒的休眠可能有效。
COMMTIMEOUTS
文档指出对于读取间隔超时:
The maximum time allowed to elapse before the arrival of the next byte on the communications line, in milliseconds. If the interval between the arrival of any two bytes exceeds this amount, the
ReadFile
operation is completed and any buffered data is returned. [...]
Asio 对文档(即强调文本)的解释是给定 ReadFile
操作,读取间隔超时开始于第一个字节被读取之后。言外之意就是如果ReadFile
被请求读取超过 0 个字节,Asio 不期望 ReadFile
操作返回一个状态,指示它已成功同步或异步读取 0 字节。通过这种解释,Asio 的 implementation将串行端口的读取间隔超时配置为 1 毫秒1。
// Set up timeouts so that the serial port will behave similarly to a
// network socket. Reads wait for at least one byte, then return with
// whatever they have. Writes return once everything is out the door.
::COMMTIMEOUTS timeouts;
timeouts.ReadIntervalTimeout = 1;
timeouts.ReadTotalTimeoutMultiplier = 0;
timeouts.ReadTotalTimeoutConstant = 0;
async_read
是在对中间 async_read_some
的零次或多次调用中实现的组合操作操作。 async_read
操作解释中间体 async_read_some
操作成功完成并传输了 0 个字节,就好像组合操作不会有进一步的进展,因此 async_read
操作完成。当底层系统调用 ReadFile
时,这种解释就会出现问题。意外同步完成并成功读取 0 字节。
有了这些细节,替代解决方案是:
ReadFile
时开始操作一旦读取了至少一个字节ReadFile
的观察行为并发现它仅在 ReadFile
时发生操作同步完成,然后可以修补 async_read_some()
在 win_iocp_handle_service::start_read_op
内运行.否则,可以修补各种 read_op
特化,以便他们的 completion predicate如果已读取 0 个字节,但已请求超过 0 个字节,则不会退出。<子>1。如果通信驱动程序的实现允许读取间隔超时,该超时从读取 ReadFile<sub>n</sub>
的最后一个字节开始操作影响ReadFile<sub>n+1</sub>
在读取间隔超时间隙内启动的操作,然后在 ReadFile<sub>n</sub>
之间休眠和 ReadFile<sub>n+1</sub>
在读取间隔超时期间,当提供的缓冲区大小大于 0 字节时,将阻止 Asio 读取操作成功完成和 0 字节。
关于c++ - boost::asio::async_read 在不满足完成条件的情况下结束,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36597923/
我想检索具有多个条件的数据,其中每个条件将在特定字段中包含特定关键字。 表结构如下: sid nid cid 数据 50 7 5 ee 50 7 6 AA 50 7 8 ff 51 7 5 ee 51
在 Prolog 中,我经常通过提供模板(包含变量的结构)然后满足其上的一组约束来解决问题。一个简单的例子可能是: go(T) :- T = [_, _, _], member(cat
在设计 FPGA 系统时,我如何粗略估计给定任务所需的逻辑 block 数量? 有人对我对这些常见设备的期望有一个粗略的数量级吗? 串口 使用 CRC32 的数据包解帧器 8 微核 我看过 www.o
我需要编写一段代码,如果函数满足列表中的大多数元素,则返回 True,不满足其中的 false。例如:moreThan odd [1,2,3] 是 True,但是 moreThan odd [1,2,
一旦满足三个条件,我需要使用 componentWillReceiveProps() 来调用我的组件中的方法。其中两个条件将当前 Prop 与下一个 Prop 进行比较,这两个条件通过 Ajax 请求
我正在构建一个主从表单。主视图模型构造细节 View 模型的实例。这些细节 View 模型有几个依赖项,需要用新 类实例来满足。 (这是因为他们需要在独立于主虚拟机的数据上下文中运行的服务层。) 实现
我有以下项目,我已经使用了一段时间。正如您在运行 snnipets 后看到的那样,一切正常。 /* The dark background behind the dialogs */ .dialog-
我正在尝试找出解决此问题的方法: 我想要一个函数来检查文本字段是否填充了文本并且复选框是否被选中。当满足这些条件时,“提交”按钮将启用。如果启用“提交”按钮后不久,用户清除文本字段或取消选中复选框,则
所以我相对较新,我有以下代码,我想知道如何制作这样我可以返回临时变量,同时满足java的返回要求。我希望返回临时值,但由于它位于 if-else block 内,因此从技术上讲,它不会在其外部初始化。
我正在编写一个脚本,该脚本读取文本文件并根据 .txt 文件的内容更改 div 中的文本。 但这不是我的问题。我不想要纯文本,背景颜色应该根据满足 if/elseif/else 函数的条件而改变。 v
我想在 if let 构造中满足多个约束。我知道我们可以使用“,”(逗号)来解包多个值,但它们都必须成功解包。 例如: var str: String? = "Hello" var x: Int? =
当我在 genymotion 模拟设备上安装我的应用程序时,它无法很好地安装,在控制台上我得到“INSTALL_FAILED_CPU_ABI_INCOMPATIBLE”我尝试了另一个应用程序,它安装得
因此,我试图根据数据帧的匹配条件来查看数据帧的两个变量(v1 和 v2)是否在其符号(正数或负数)中匹配变量(ID1==ID2)。 示例数据框 - Trial.df: ID1 v1
如果交付一个 Java 应用程序,它使用 gradle 依赖管理和许多来自 maven-central 的开源库,是否足以检查第一级 depedencies 的许可证(因为他们的依赖关系必须再次自动与
我正在尝试创建一个满足接口(interface) Iterable 的类“Gprogram” (这样我就可以在我的 Gprogram 中迭代 Gcommand)。但是,我只能使用类型 Iterable
我想知道是否可以获得一些帮助。 我试图在查询中写入一个查询,我使用 3 个字段:ID、选项和金额。 我需要对我的唯一 ID 进行分组,然后在该组中我需要按选项白色进行拆分,总计每个选项的金额。例如:编
如何在iOS swift项目中配置Jitsi-meet框架开启视频通话服务? 最佳答案 编辑:这也适用于 Xcode Version 12.2 (12B45b)在 Mac OS Big Sur 上。
我正在玩一些交互式菜单,目前有一个隐藏菜单,当按下一个按钮时,它会从右边出现,并将整个内容移到上面。有点像移动 facebook 应用程序。为了确定按钮应该将菜单滑出还是放回我使用 javascrip
我的目标很简单,使用遗传算法重现经典的“Hello, World”字符串。 我的代码基于此 post .代码主要包含4个部分: 生成具有多个不同个体的种群 根据与target的比较,定义评估个体好坏的
问题陈述 我们有一个雇主想要面试 N 个人,因此安排了 N 个面试时段。每个人都有这些时段的忙闲时间表。给出一个算法,如果可能的话将 N 个人安排到 N 个槽位,如果不可能则返回一个标志/错误/等。最
我是一名优秀的程序员,十分优秀!