我有一个应用程序,它运行在与不同传感器连接的控制硬件上。在加载应用程序时,它会逐个检查各个传感器,以确定是否根据预定义的协议与传感器进行了正确的通信。
现在,我已经实现了将单个传感器通信检查为单例线程的代码,以下是运行函数,它使用select系统调用和管道进行进程间通信,以指示线程结束。
void SensorClass::run()
{
mFdWind=mPort->GetFileDescriptor();
fd_set readfs;
int max_fd = (mFdWind > gPipeFdWind[0] ? mFdWind : gPipeFdWind[0]) + 1;
int res;
mFrameCorrect=false;
qDebug("BEFORE WHILE");
while(true)
{
qDebug("\n IN WHILE LOOP");
usleep(50);
FD_ZERO(&readfs);
FD_SET(mFdWind,&readfs);
FD_SET(gPipeFdWind[0],&readfs);
res=select(max_fd,&readfs,NULL,NULL,NULL);
if(res < 0)
perror("Select Failed");
else if(res == 0)
puts("TIMEOUT");
else
{
if(FD_ISSET(mFdWind,&readfs))
{
puts("*************** RECEIVED DATA ****************");
mFrameCorrect=false;
FlushBuf();
//int n=mPort->ReadPort(mBuf,100);
int n=mPort->ReadPort(mBuf,100);
if(n>0)
{
Count++;
QString str((const char*)mBuf);
//qDebug("\n %s",qPrintable(str));
//See if the Header of the frame is valid
if(IsHeaderValid(str))
{
if( (!IsCommaCountOk(str)) || (!IsChecksumOk(str,mBuf)) || (!CalculateCommaIndexes(str)) )
{
qDebug("\n not ok");
mFrameCorrect=false;
} //if frame is incorrect
else
{
qDebug("\n OK");
mFrameCorrect=true;
}//if frame is correct(checksum etc are ok)
}//else if header is ok
}//if n > 0
}//if data received FD_ISSET
if(FD_ISSET(gPipeFdWind[0],&readfs))
break;
}//end nested else res not <= 0
}//infinite loop
}
以上线程从主GUI线程开始运行。这很好。问题是我给了用户一个随意重新测试子系统的选项。为此,我使用
删除单例实例delete SensorClass::instance();
然后使用
重启单例SensorClass::instace()->start();
问题是这次控制是在run()函数的while循环中出现的,当进入while循环时,我的猜测是管道读取再次从写入管道读取到最后一次。我曾尝试使用fflush()来清除I / O但没有运气。 我的问题是
我是否正在考虑正确的方向?
如果是,那么我们如何清除管道?
如果没有人可以提出为什么选择性重新测试不起作用?
提前致谢..
答案 0 :(得分:1)
fflush
清除输出缓冲区。如果要清除输入缓冲区,则需要读取数据或搜索到最后。
我不相信“单身人士”模式是合适的。还有其他方法可以确保每个硬件最多只有一个实例。如果您以后想要多个线程,每个线程使用不同的传感器怎么办?
答案 1 :(得分:1)
让我们假设你是通过继承QThread(你没有指定)来创建这个线程的。来自QThread::~QThread ()的文档:
因此声明delete SensorClass::instance();
可能是一个非常非常糟糕的主意。特别是,考虑到这个缺陷,对这个程序的行为有任何意义。在继续之前,您可能希望找到一种方法来删除实例并确保线程也消失。
另一个问题浮现在脑海中。当你运行delete SensorClass::instance()
时,你会摆脱一些对象(在堆上,人们希望)。谁告诉单身人士持有人它的对象已经消失了?例如。以便下一次调用SensorClass::instance()
知道它需要分配另一个实例?这是否在SensorClass::~SensorClass
中正确处理?
假设这不是问题。这可能意味着指向实例的指针保存在全局变量(或者,例如类级静态成员)中。它可能对这种情况无关紧要,但访问该成员是否正确同步?即有没有一个互斥锁被锁定每次访问它?
答案 2 :(得分:1)
你真的不想在线程中运行初始化。这是第一个让你的问题大大复杂化的问题,而且出于某种原因没有人指出这种问题。
只需将初始化作为自己的函数,然后有一个保护变量并锁定,并在启动时将所有使用它的东西分别初始化。
答案 3 :(得分:0)
所以你通过向管道写东西来发信号,管道只创建一次 - 即在后来的线程中重用?
远离管道读取信号。假设你通过写一个字节来发信号,那么你可以做类似的事情(NB,没有错误检查等):
if(FD_ISSET(gPipeFdWind[0],&readfs)) {
char c;
read(gPipeFdWind[0], &c, 1);
break;
}
还有 用于处理套接字I / O的Qt类,例如: QTcpSocket,这将使代码不仅更清洁,也更加跨平台。或者至少QSocketNotifier来抽象选择。