我有一个程序,通过国家仪器公司(NI)的ADC系统记录数据。
设备缓冲信息一段时间,然后程序在某个时刻收集缓冲数据。如果程序收集的数据大于缓冲区,那么缓冲区将不得不在我的程序没有接收到数据的情况下释放,这将导致NI库抛出异常,表示请求的数据不再可用,因为它已经丢失。
由于我的程序是一个命令提示程序,如果用户点击并按住滚动条,程序就会暂停,这可能会导致这个问题的发生。
如何在不增加缓冲区大小的情况下解决这个问题?我可以在Windows中禁用这个保持功能吗?
谢谢。
只有试图输出到控制台的线程被阻止。把它作为一个单独的线程,你的问题就会消失。
当然,您需要缓冲您的输出,并在缓冲区溢出时采取合理的措施。
作为参考,这是我用来测试的简单代码,你会注意到,即使滚动条被按下,计数器也会继续增加:
#include <Windows.h>
#include <stdio.h>
volatile int n = 0;
DWORD WINAPI my_thread(LPVOID parameter)
{
for (;;)
{
n = n + 1;
Sleep(800);
}
}
int main(int argc, char ** argv)
{
if (!CreateThread(NULL, 0, my_thread, NULL, 0, NULL))
{
printf("Error %u from CreateThreadn", GetLastError());
return 0;
}
for (;;)
{
printf("Hello! We're at %un", n);
Sleep(1000);
}
return 0;
}
虽然可能有一些方法可以绕过你可能想到的输出中的每个单独的问题[例如,在网络上运行有时很慢的输出链接,或者诸如此类],但我认为正确的做法是断开你的输出与数据收集的连接。添加一个单独的线程来收集数据,并将主线程显示在命令提示符窗口中,这样做应该不难。这样,无论Windows向你抛出哪种"输出被阻止"变体,它都会起作用——至少在你的RAM用完之前是这样,但在那一点上,这是你的程序决定做什么[例如丢弃一些数据或类似的]。
通常情况下,"我需要收集一些东西,我也需要允许用户查看数据,但我不希望两者相互干扰"的问题就是这样解决的。
首先使用GetConsoleWindow winapi函数并获取控制台的HWND。现在我建议两种方法,
方法I通过创建自己的WindowProcedure来对窗口进行子类化。(从这里寻求帮助)既然已经将其子类化了,就可以截取WM_VSCROLL和WM_HSCROLL消息,并对代码进行自己的补救。
方法二使用诸如SetWindowPos之类的函数来更改窗口的大小,这样就不需要滚动条了。或更改控制台屏幕缓冲区的大小,以便不需要滚动条。
方法I对应用程序有很大的控制权,但它比非常简单的方法II有点复杂。如果要禁止用户调整控制台窗口的大小,只需从控制台窗口的WindowStyle中删除WS_THICKFRAME
即可。
我也处于类似的情况,发现这种阻塞行为可能是由命令提示符的快速编辑"功能"引起的。这个问题解释了它,答案显示了如何禁用它。希望这有帮助,即使几年后:)