求救线程安全问题!希望高人多多指教!
很烦的问题,有那位高人可以指点一下:
线程操作串口,每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;
}
...全文
相关推荐
OmniPeek.Enterprise.v6.5_keygen
无线 嗅探器 wifi WLAN sniffer OmniPeek Enterprise v6.5 keygen 注册鸡
WildPackets OmniPeek Enterprise with Enhanced Voice Option v5.0
WildPackets OmniPeek Enterprise with Enhanced Voice Option v5.0 part07.rar 由于文件较大,故此分割了12部分,下载时一定要下全。
Omnipeek.Enterprise.11.0.1
Omnipeek.Enterprise.11.0.1
PostgreSQL高可用之主备复制
多个PostgreSQL可协同工作,如果主库发生宕机备库将迅速进行接管并对外提供服务以实现高可用。本文将从主备复制、主备切换、故障转移等角度进行实际测试演练。第一章主备复制是基础,通过主备复制可以得到一个或多个相同的实例。在主备复制的基础上通过第二章主备切换介绍了如何手工将主库与备库互换角色。在第三章中,采用了Keepalived进行实时监测,在主库宕机后,使用主备切换中提到的命令使备库升级为主库并对外提供服务,以达到PostgreSQL高可用的目标。
SAP PS项目结算实操:从CJ20N到CJ88,手把手搞定项目成本结转与凭证生成
本文详细解析SAP PS项目结算全流程,从CJ20N到CJ88的操作要点,涵盖成本归集、结算规则配置、结果分析及凭证生成等关键环节。特别针对FICO模块中的项目凭证流转问题提供实战解决方案,帮助财务人员规避常见配置错误,提升项目结算效率与准确性。


