问题描述:

I checked related posts but still cannot get the answer. Experts, please help me on this.

I basically has two threads, one thread recv data from the ethernet and the other process the received data. To get the maximum performance, ThreadRecv recv nth frame and ThreadCompute Process (n-1)th frame. I recorded the timing relation and found that if the event is signaled before the Wait function, it will not get the event.

Here is the rough code:

st_threads::st_threads():Event_ComputeDone(0,0),Sem_KillThread(0,2),

Sem_PauseThread(0,2),Sem_ResumeThread(0,2),Event_RecvDone(0,0),

Event_RecvTerminated(0,0),Event_RecvPaused(0,0),Event_RecvStart(0,0),//make it automatic

Event_ComputeTerminated(0,0),Event_ComputePaused(0,0)

{

ping_num=0;

thread_state=stopped;

step=1;

//threadHandles[0]=0;

//threadHandles[1]=0;

}

UINT st_threads::ThreadRecv(LPVOID pParam)

{

st_threads *pThread=(st_threads*)pParam; //get the pointer

hptime t0;

double dtime,dtime0;

while(1)

{

dtime0=t0.gettime();

//check if terminate the thread

if(pThread->ping_num)

WaitForSingleObject(pThread->Event_RecvStart,INFINITE);

//realtime processing

dtime=t0.gettime();

switch(pThread->work_mode)

{

case realtime_mode:

//if(pThread->ECP->IsAlive())

{

pThread->frame_len=pThread->ECP->RecvDataFrame(pThread->rawbuf,MAX_RAW_BUF_SIZE); //receive a data frame into a buffer

if(pThread->frame_len<192)

{

pThread->frame_len=pThread->ECP->RecvDataFrame(pThread->rawbuf,MAX_RAW_BUF_SIZE); //receive a data frame into a buffer

}

if(pThread->frame_len<0)

{

TRACE("recv error\n");

}

pThread->pdatalist->push_back(raw_data(pThread->frame_len,pThread->rawbuf,pThread->ping_num));

pThread->praw_frame[pThread->ping_num%2]=--pThread->pdatalist->raw_buf.end();

}

break;

default:break;

}

pThread->ping_num++;

pThread->Event_RecvDone.SetEvent(); //let compute to start

pThread->threadtime.time_ThreadRecv=dtime0;

pThread->threadtime.dt_recv=t0.gettime()-dtime;

pThread->threadtime.dt_ThreadRecv=t0.gettime()-pThread->threadtime.time_ThreadRecv;

//

//TRACE("RECV:ping#=%d\n",pThread->ping_num);

}

AfxEndThread(0);

return 0;

}

UINT st_threads::ThreadCompute(LPVOID pParam)

{

st_threads *pThread=(st_threads*)pParam;

int prev_frame_time=0,data_mode;

double time_elapsed,dt,dtime0;

hptime t0;

while(1)

{

//WaitForSingleObject(pThread->Event_ComputeStart,INFINITE);

dtime0=t0.gettime();

WaitForSingleObject(pThread->Event_RecvDone,INFINITE);

pThread->Event_RecvStart.SetEvent(); //let recv start at the same time as computing

//realtime processing

if(pThread->ping_num)

{

dt=t0.gettime();

pThread->dispatch_packet(pThread->praw_frame[(pThread->ping_num-1)%2],&data_mode,pThread->ping_num-1);

pThread->threadtime.dt_comp=t0.gettime()-dt;

pThread->threadtime.dt_frame_interval=t0.gettime()-dtime0;

}

//else Sleep(100);

pThread->Event_ComputeDone.SetEvent();

pThread->threadtime.time_ThreadCompute=dtime0;

pThread->threadtime.dt_ThreadCompute=dt=t0.gettime()-pThread->threadtime.time_ThreadCompute;

if(pThread->debug_mode) pThread->logtime(pThread->ping_num,data_mode);

//TRACE("COMP:ping#=%d, frame rate: %d\n",pThread->ping_num,int(1000.0/dt));

//

}

AfxEndThread(0);

return 0;

}

The program will record the timing, part of the output would be like this:

0177 15 364486101 23 23 364486099 23 21 23

0178 15 364486124 23 23 364486122 23 21 23

0179 15 364486147 23 23 364486145 23 20 23

0180 15 364486170 23 23 364486167 23 21 23

0181 15 364486193 23 23 364486190 23 21 23

0182 15 364486216 21 21 364486213 23 20 21

0183 15 364486238 23 23 364486236 23 21 23

0184 15 364486261 23 23 364486259 23 21 23

0185 15 364486284 22 22 364486282 23 21 22

0186 15 364486307 23 23 364486305 23 21 23

0187 15 364486330 23 23 364486328 23 21 23

0188 15 364486353 23 23 364486351 23 20 23

0189 15 364486376 23 22 364486374 23 20 23

0190 15 364486399 23 23 364486396 23 21 23

0191 15 364486422 23 23 364486420 23 21 23

0192 15 364486445 23 23 364486442 23 21 23

0193 15 364486468 23 23 364486465 23 20 23

0194 15 364486491 22 22 364486488 23 20 22

0195 15 364486513 23 23 364486511 23 21 23

0196 15 364486536 23 23 364486534 23 21 23

0197 15 364486559 22 22 364486557 23 21 22

0198 15 364486582 23 23 364486580 23 21 23

0199 15 364486605 23 23 364486603 23 20 23

0200 15 364486628 23 23 364486625 25 23 23

0200 15 364486651 23 23 364486625 25 23 23

0201 15 364486674 24 22 364486650 26 25 24

0202 15 364486698 25 22 364486676 25 25 25

0203 15 364486723 26 23 364486701 25 25 26

0204 15 364486749 25 23 364486726 25 25 25

0205 15 364486774 24 22 364486751 25 25 24

0206 15 364486798 26 22 364486776 26 26 26

0207 15 364486825 24 21 364486802 25 25 24

0208 15 364486849 25 22 364486827 25 25 25

0209 15 364486874 25 22 364486852 25 25 25

0210 15 364486900 25 22 364486877 25 25 25

0211 15 364486925 25 22 364486902 26 25 25

0212 15 364486950 25 22 364486928 25 25 25

0213 15 364486975 26 22 364486953 26 26 26

0214 15 364487001 26 22 364486979 26 26 26

0215 15 364487027 24 22 364487004 25 25 24

0216 15 364487051 25 22 364487029 25 25 25

0217 15 364487076 29 22 364487054 29 29 29

0218 15 364487106 26 23 364487083 26 26 26

0219 15 364487132 25 22 364487109 26 26 25

The first column is the ping number, 2nd is not related, 3rd is absolute time for ThreadCompute, 4th is duration time for ThreadCompute, 5th not releated, 6th is for ThreadRecv, 7th is duration time for threadRecv.

Note that we get two identical output with ping number 200. It shows that the threadrecv is a little bit slower than ThreadCompute. The recvStart is issued earlier than the Wait function, and it is not received.

网友答案:

It's a totally wrong design.

 WaitForSingleObject(pThread->Event_RecvDone,INFINITE);
 pThread->Event_RecvStart.SetEvent(); //let recv start at the same time as computing

You wait on a packet (identified by ping_num) to be received and tell the Receiver thread to go on receiving and then start processing the packet. The Receiver thread could increments ping_num BEFORE the Computing thread finishes processing the just received packet. That's totally possible in a multithreaded environment.

I think you should re-design the logic of receive/compute process. Better use a list or queue to store received packets in Receiver thread and extract them in Computing thread. Of course you have to use Mutex or other means to protect the list/queue.

相关阅读:
Top