当前位置: 代码迷 >> VC/MFC >> 为啥这线程处理数据占用COU将70%-80%
  详细解决方案

为啥这线程处理数据占用COU将70%-80%

热度:147   发布时间:2016-05-02 03:38:18.0
为什么这线程处理数据占用COU将70%-80%
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;
}

------解决思路----------------------
引用:
Quote: 引用:

你最好是在OnReceive接收数据完了之后以通知的方式唤醒Thead1线程,比如事件HEVENT,这样Thead1线程就不至于没数据处理也在那儿做无谓的循环

不过理论上sleep 200 CPU使用率应该会下来的,你Thead1数据处理完之后pdlg->flen置0了吗?


不是0,这个数据是很长  很多数据,大概结构是数据头和数据 ,我用2个线程主要处理这个数据解析出来,平时一个线程处理太慢了


那你另外一个线程怎么写的??
------解决思路----------------------
cpu很正常,当你连续执行大运算的时候,当然希望CPU以100%的能力投入运行,难道你希望CPU走一下停一下?
------解决思路----------------------
引用:
Quote: 引用:


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
------解决思路----------------------
引用:
Quote: 引用:

另外你那些错误不需要捕获把

不需要,ResetEvent  复位这些都不用了吗? 直接用这个
for(;;)
{
::WaitForSingleObject(m_event,3000) == WAIT_TIMEOUT
....
...
..
}
这样等待就可以了?我去试试

在创建事件的时候设置为自动重置的!每次SetEvent完,wait调用后会重置的
  相关解决方案