求救线程安全问题!希望高人多多指教!

tonsz 2006-06-20 08:49:42

很烦的问题,有那位高人可以指点一下:

线程操作串口,每0.5ms发送一次读数据请求,并接收一次数据
操作系统为WinXP,CPU空闲时,收发都正常,
但是一开大程序,CPU忙时,就收数不正确。
线程的优先级不能提得太高,因为定时的查询会使系统不响应
而较低的优先级和空闲模式都会出错。
线程操作的都是全局变量。

不知是因为什么原因造成的,
线程的安全很不好做呀!
有什么好的建议没有呀?
急需各位高人指点。
小的谢了先!


部分源代码:

/*---------------------------------------------------------------------------
Function Name:TFormMain::FormCreate
Usefullness:创建线程
About in Parameter:
About out Parameter:
The date:2004-10-30 11:17:09
---------------------------------------------------------------------------*/

void __fastcall TFormMain::StartSampleClick(TObject *Sender)
{

nCurrentHndShk = 0;
bFlagTerminateThread = true;
QueryPerformanceFrequency(&rFreq);
rInterval.QuadPart = dPickGap * rFreq.QuadPart / 1000;
QueryPerformanceCounter(&rStart);

DWORD ThreadID;
HANDLE hthread = CreateThread(0, 0, TimerThreadProc, 0, 0, &ThreadID);

if (hthread == 0)
{
ShowMessage("线程创建失败!");
if (hComm == 0) return;
// 实际关闭通信端口
CloseHandle(hComm );
return;
}
SetThreadPriority(hthread, THREAD_PRIORITY_IDLE);


}



/*---------------------------------------------------------------------------

Function Name:TimerThreadProc
Usefullness:定时的发送握手命令 
About in Parameter:
About out Parameter:
The date: 2006-3-13 9:09:09
---------------------------------------------------------------------------*/

DWORD CALLBACK TimerThreadProc(void * p)
{
DWORD nBytesRead,dwCommError,i,ReadLen;
COMSTAT CS;
do {
rEnd.QuadPart = rStart.QuadPart + rInterval.QuadPart;
do {
QueryPerformanceCounter(&rStart);
} while (rStart.QuadPart < rEnd.QuadPart);
rStart = rEnd;


switch (nCuntHndCyc)
{
//头一次发握手信号,不用接收
case 0:

PurgeComm(hComm, PURGE_RXCLEAR); // 清除COM 资料
WriteFile(hComm,&byHnd[nCurrentHndShk],1, &lrc, NULL);
nCuntHndCyc = 1;
break;
//nCuntHndCyc为一,即已经等待了一个周期,
//开始接收数据,并完成数据转化
//清空串口数据,开始下一次发送握手信号
//nCuntHndCyc为二时,表示为接收完全部数据又等待了一个周期
//如果还是没有收到,进行三的状态,进行重新发送
case 1:
case 2:
//使用ClearCommError得知有多少的数据在缓冲区中
ClearCommError(hComm,&dwCommError,&CS); //取得状态

if (CS.cbInQue >= 4) //!= 0) //若缓冲区有足够数据,则读取
{
ReadLen = CS.cbInQue;
if (ReadLen > sizeof(szInputBuffer))
{

PurgeComm(hComm, PURGE_RXCLEAR); // 清除COM 资料
WriteFile(hComm,&byHnd[nCurrentHndShk],1, &lrc, NULL);

}
else
{
//读取数据
if (ReadFile(hComm, szInputBuffer,ReadLen,&nBytesRead,NULL)) // 接收COM 的数据
{

// PurgeComm(hComm, PURGE_RXCLEAR); // 清除COM 资料
nCurrentHndShk = (nCurrentHndShk < nTotleHndShk) ? (nCurrentHndShk+1):0;
// for (int i=0; i<5; i++)
WriteFile(hComm,&byHnd[nCurrentHndShk],1, &lrc, NULL);


//将数据搬到数组中
for (i=0; i<4; i++)
byInputByteData[i] = szInputBuffer[i];

if((byInputByteData[0]&0x80)==0x80)
//负数转换
{
bb[0]=byInputByteData[3];
bb[1]=byInputByteData[2];
bb[2]=byInputByteData[1];//&0x7f);
bb[3]=byInputByteData[0];
lAData=(long)*dw-(long)0x100000000;
}
else
//正数转换
{
bb[0]=byInputByteData[3];
bb[1]=byInputByteData[2];
bb[2]=byInputByteData[1];
bb[3]=byInputByteData[0];
lAData=(long)*dw;
}
dbCurrentValue[nCurrentHndShk] += lAData;
nCount[nCurrentHndShk]++;


} //End ReadFile
}//else Loop


}
else
{
nCuntHndCyc++;
}

break;
case 3:
PurgeComm(hComm, PURGE_RXCLEAR);
nCuntHndCyc = 1;
// for (int i=0; i<5; i++)
WriteFile(hComm,&byHnd[nCurrentHndShk],1, &lrc, NULL);
break;

default:
PurgeComm(hComm, PURGE_RXCLEAR);
nCuntHndCyc = 1;
// for (int i=0; i<5; i++)
WriteFile(hComm,&byHnd[nCurrentHndShk],1, &lrc, NULL);
break;
}//End switch (nCuntHndCyc)

}while (bFlagTerminateThread);

return 0;
}





...全文
218 7 打赏 收藏 转发到动态 举报
写回复
用AI写文章
7 条回复
切换为时间正序
请发表友善的回复…
发表回复
FlySkyFree 2006-07-11
  • 打赏
  • 举报
回复
这样定时5ms是否可以:
t = GetTickCount();
.............//中间的过程
GetTickCount() - t < 5
wenyongjie 2006-07-09
  • 打赏
  • 举报
回复
MARK
tonsz 2006-07-06
  • 打赏
  • 举报
回复
技术有待高人指点呀!
如何定5ms的时钟,而且正确的操作串口?
总是,计算机CPU一忙,就接收不正常
zwh202342 2006-06-24
  • 打赏
  • 举报
回复
本人得串口程序,不过你的自己改改,这个市串口接收数据时判定返回的数据是不是空得
Sleep(200);
String sn="";
const BufSize = 4096;
unsigned char Buffer[BufSize];
int nBytes = 0;
while((nBytes=txzlcom->ReadPackage(Buffer,BufSize))>0)
{
AnsiString s;
for(int i=0; i<nBytes; i++)
s += IntToHex(Buffer[i],2) + " ";
s = s.Trim();

if(!s.IsEmpty())
{
sn = sn + IntToHex(Buffer[4],0);
}
}
if (sn != "")
{
......
}
else
{
startbtn->Enabled = true;

}
tonsz 2006-06-23
  • 打赏
  • 举报
回复
请大家多多指点呀!
tonsz 2006-06-22
  • 打赏
  • 举报
回复
高人请继续指点迷经呀!

我的程序没有用中断
因为系统中断的响应时间比较长,
不能满足定时的要求吧!

串口操作不是有可以设置的缓冲区的么?
我设置的应该足够大了,

是说 ClearCommError(hComm,&dwCommError,&CS); //取得状态
取到的是不一定对么?

怎么使用事件内核对象通知呀?
不知时间上是不是满足要求,
而且请给个例子什么的做个参考,好么?
xiaoshi0 2006-06-21
  • 打赏
  • 举报
回复
你的串口操作是怎么样的呢?

一般的串口操作都是中断式的,当串口有信息到达的时候会产生一个中断。

优先级如果设置高的话,如果你的查询时间比较长,会导致系统其他进程无法得到CPU时间;

优先级如果设置低的话,可能根本就不会得到CPU时间,因为这是系统有高优先级的线程;

串口操作一般都是实时的,如果你有数据没有读取,可能会在下一个中断时冲掉,

所以每次你请求度取的时候,要保证缓冲区中有数据,可以通过一个事件内核对象来通知你。

13,826

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder相关内容讨论区
社区管理员
  • 基础类社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧