m_Buffer 是char[4096]大小的函数里全局变量,负责将接受到的数据累计起来
下面是我的接受数据, 这个接受数据本身也是一个线程,我现在想开辟2个线程处理数据,可是CPU占用70%!求赐教那地方没写好! (线程1和线程2在下面)
我的思路是 全局变量 接受数据 flen += iLength; //记录位置 也就是下一次数据来了接着从这个位置
下面是线程里移动位置
pdlg->flen -= (packetTick + 6); //设置当前的位置
memcpy(pdlg->m_Buffer , pdlg->m_Buffer + packetTick + 6, pdlg->flen); 这个是处理数据后将前面的数据移除,向前进为,进的位置是数据的大小
memset( pdlg->m_Buffer + pdlg->flen , 0, packetTick + 6 ) ;//这个是将后面的多余数据置0
我也不知道是不是我的思路或者哪里出问题了,导致现在CPU很高,请问是不是有其他的方法改变?
EnHandleResult LoginServer::OnReceive(IClient* pClient, const BYTE* pData, int iLength)
{
_MY_TRY
{
//Fill((char*)pData,iLength);
//CString stemp;
EnterCriticalSection(&g_CriticalSection);
memcpy(m_Buffer + flen ,pData ,iLength);
shuxing->LogLogin("单接受:"+ FormatOut(pData,iLength));
flen += iLength; //设置当前的位置
shuxing->LogLogin("总接受:"+ FormatOut((BYTE*)m_Buffer,flen));
TRACE("iLength:%d flen:%d \r\n",iLength,flen);
LeaveCriticalSection(&g_CriticalSection);
}
_MY_CATCH
{
}
return HR_OK;
}
//线程1
DWORD WINAPI LoginServer::Thread1(LPVOID lpParmeter)
{
LoginServer* pdlg = (LoginServer*)lpParmeter;
CHAR header[PACKET_HEADER_SIZE];
unsigned short packetID;
WORD packetuint, packetSize, packetIndex;
WORD packetTick;
char readbuff[DTINPUTSIZE];
for (;;)
{
EnterCriticalSection(&pdlg->g_CriticalSection);
if (pdlg->flen <=0)
{
LeaveCriticalSection(&pdlg->g_CriticalSection);
continue;
}
memcpy( header ,pdlg->m_Buffer , sizeof(header) ); //拷贝head
memcpy( &packetID, &header[0], sizeof(unsigned short) );
memcpy( &packetTick, &header[sizeof(WORD)], sizeof(WORD) );
memcpy( &packetuint, &header[sizeof(WORD)+sizeof(WORD)], sizeof(WORD) );
packetIndex = HIBYTE(packetuint);
packetSize= LOBYTE(packetuint);
memset(readbuff , 0 ,DTINPUTSIZE);
memcpy(readbuff,pdlg->m_Buffer,(packetTick + 6));
pdlg->shuxing->LogLogin("线程1:" + pdlg->FormatOut((BYTE*)readbuff,packetTick + 6));
pdlg->flen -= (packetTick + 6); //设置当前的位置
memcpy(pdlg->m_Buffer , pdlg->m_Buffer + packetTick + 6, pdlg->flen);
memset( pdlg->m_Buffer + pdlg->flen , 0, packetTick + 6 ) ;
LeaveCriticalSection(&pdlg->g_CriticalSection);
pdlg->hFill(packetID, readbuff, 0);
Sleep(200);
}
return 0;
}
------解决思路----------------------
continue;
这句前面也加上Sleep(200);
------解决思路----------------------
你最好是在OnReceive接收数据完了之后以通知的方式唤醒Thead1线程,比如事件HEVENT,这样Thead1线程就不至于没数据处理也在那儿做无谓的循环
不过理论上sleep 200 CPU使用率应该会下来的,你Thead1数据处理完之后pdlg->flen置0了吗?
------解决思路----------------------
HEVENT g_hEvent = NULL;
创建Thead1线程之前:
//创建一个手动复位,初始状态为无信号的事件内核对象
g_hEvent = CreateEvent(NULL,TRUE,FALSE,_T("xxoo"));
EnHandleResult LoginServer::OnReceive(IClient* pClient, const BYTE* pData, int iLength)
{
_MY_TRY
{
//Fill((char*)pData,iLength);
//CString stemp;
EnterCriticalSection(&g_CriticalSection);
memcpy(m_Buffer + flen ,pData ,iLength);
shuxing->LogLogin("单接受:"+ FormatOut(pData,iLength));
flen += iLength; //设置当前的位置
shuxing->LogLogin("总接受:"+ FormatOut((BYTE*)m_Buffer,flen));
TRACE("iLength:%d flen:%d \r\n",iLength,flen);
SetEvent(g_hEvent); //使事件对象有信号
LeaveCriticalSection(&g_CriticalSection);
Sleep(100); //也挂起一下
}
_MY_CATCH
{
}
return HR_OK;
}
DWORD WINAPI LoginServer::Thread1(LPVOID lpParmeter)
{
LoginServer* pdlg = (LoginServer*)lpParmeter;
CHAR header[PACKET_HEADER_SIZE];
unsigned short packetID;
WORD packetuint, packetSize, packetIndex;
WORD packetTick;
char readbuff[DTINPUTSIZE];
for (;;)
{
::WaitForSingleObject(g_hEvent,INFINITE); //直到g_hEvent有信号该函数才返回
EnterCriticalSection(&pdlg->g_CriticalSection);
if (pdlg->flen <=0)
{
LeaveCriticalSection(&pdlg->g_CriticalSection);
continue;
}
memcpy( header ,pdlg->m_Buffer , sizeof(header) ); //拷贝head
memcpy( &packetID, &header[0], sizeof(unsigned short) );
memcpy( &packetTick, &header[sizeof(WORD)], sizeof(WORD) );
memcpy( &packetuint, &header[sizeof(WORD)+sizeof(WORD)], sizeof(WORD) );
packetIndex = HIBYTE(packetuint);
packetSize= LOBYTE(packetuint);
memset(readbuff , 0 ,DTINPUTSIZE);
memcpy(readbuff,pdlg->m_Buffer,(packetTick + 6));
pdlg->shuxing->LogLogin("线程1:" + pdlg->FormatOut((BYTE*)readbuff,packetTick + 6));
pdlg->flen -= (packetTick + 6); //设置当前的位置
memcpy(pdlg->m_Buffer , pdlg->m_Buffer + packetTick + 6, pdlg->flen);
memset( pdlg->m_Buffer + pdlg->flen , 0, packetTick + 6 ) ;
ResetEvent(g_hEvent); //复位,使g_hEvent无信号
LeaveCriticalSection(&pdlg->g_CriticalSection);
pdlg->hFill(packetID, readbuff, 0);
Sleep(200);
}
return 0;
}
用完别忘了CloseHandle(g_hEvent)
------解决思路----------------------
DWORD WINAPI LoginServer::Thread1(LPVOID lpParmeter)
{
LoginServer* pdlg = (LoginServer*)lpParmeter;
CHAR header[PACKET_HEADER_SIZE];
unsigned short packetID;
WORD packetuint, packetSize, packetIndex;
WORD packetTick;
char readbuff[DTINPUTSIZE];
for (;;)
{
::WaitForSingleObject(g_hEvent,INFINITE); //直到g_hEvent有信号该函数才返回
if (pdlg->flen <=0)
{
ResetEvent(g_hEvent); //复位,使g_hEvent无信号
Sleep(200);
continue;
}
EnterCriticalSection(&pdlg->g_CriticalSection);
memcpy( header ,pdlg->m_Buffer , sizeof(header) ); //拷贝head
memcpy( &packetID, &header[0], sizeof(unsigned short) );
memcpy( &packetTick, &header[sizeof(WORD)], sizeof(WORD) );
memcpy( &packetuint, &header[sizeof(WORD)+sizeof(WORD)], sizeof(WORD) );
packetIndex = HIBYTE(packetuint);
packetSize= LOBYTE(packetuint);
memset(readbuff , 0 ,DTINPUTSIZE);
memcpy(readbuff,pdlg->m_Buffer,(packetTick + 6));
pdlg->shuxing->LogLogin("线程1:" + pdlg->FormatOut((BYTE*)readbuff,packetTick + 6));
pdlg->flen -= (packetTick + 6); //设置当前的位置
memcpy(pdlg->m_Buffer , pdlg->m_Buffer + packetTick + 6, pdlg->flen);
memset( pdlg->m_Buffer + pdlg->flen , 0, packetTick + 6 ) ;
ResetEvent(g_hEvent); //复位,使g_hEvent无信号
LeaveCriticalSection(&pdlg->g_CriticalSection);
pdlg->hFill(packetID, readbuff, 0);
Sleep(200);
}
return 0;
}
------解决思路----------------------
那你另外一个线程怎么写的??
------解决思路----------------------
cpu很正常,当你连续执行大运算的时候,当然希望CPU以100%的能力投入运行,难道你希望CPU走一下停一下?
------解决思路----------------------
DWORD WINAPI LoginServer::Thread1(LPVOID lpParmeter)
{
LoginServer* pdlg = (LoginServer*)lpParmeter;
CHAR header[PACKET_HEADER_SIZE];
unsigned short packetID;
WORD packetuint, packetSize, packetIndex;
WORD packetTick;
char readbuff[DTINPUTSIZE];
for (;;)
{
::WaitForSingleObject(g_hEvent,INFINITE); //直到g_hEvent有信号该函数才返回
if (pdlg->flen <=0)
{
ResetEvent(g_hEvent); //复位,使g_hEvent无信号
Sleep(200);
continue;
}
EnterCriticalSection(&pdlg->g_CriticalSection);
memcpy( header ,pdlg->m_Buffer , sizeof(header) ); //拷贝head
memcpy( &packetID, &header[0], sizeof(unsigned short) );
memcpy( &packetTick, &header[sizeof(WORD)], sizeof(WORD) );
memcpy( &packetuint, &header[sizeof(WORD)+sizeof(WORD)], sizeof(WORD) );
packetIndex = HIBYTE(packetuint);
packetSize= LOBYTE(packetuint);
memset(readbuff , 0 ,DTINPUTSIZE);
memcpy(readbuff,pdlg->m_Buffer,(packetTick + 6));
pdlg->shuxing->LogLogin("线程1:" + pdlg->FormatOut((BYTE*)readbuff,packetTick + 6));
pdlg->flen -= (packetTick + 6); //设置当前的位置
memcpy(pdlg->m_Buffer , pdlg->m_Buffer + packetTick + 6, pdlg->flen);
memset( pdlg->m_Buffer + pdlg->flen , 0, packetTick + 6 ) ;
ResetEvent(g_hEvent); //复位,使g_hEvent无信号
LeaveCriticalSection(&pdlg->g_CriticalSection);
pdlg->hFill(packetID, readbuff, 0);
Sleep(200);
}
return 0;
}
为什么要修改成这样? 在没进入事件区时候
事件通知啊,你没接触过线程同步吧? 只有当m_Buffer有新数据的时候再开始对m_Buffer的处理
另外你不要搞两个一模一样的线程去处理m_Buffer,你不怕乱掉吗?即便你控制的很好,两个一模一样的线程是很浪费资源的,殊不知CPU在两个线程之间执行调度是要额外消耗CPU和系统资源的??
------解决思路----------------------
_MY_TRY
_MY_CATCH
------解决思路----------------------
另外你那些错误不需要捕获把
不需要,ResetEvent 复位这些都不用了吗? 直接用这个
for(;;)
{
::WaitForSingleObject(m_event,3000) == WAIT_TIMEOUT
....
...
..
}
这样等待就可以了?我去试试
在创建事件的时候设置为自动重置的!每次SetEvent完,wait调用后会重置的