[英]WaitforSingleObject missed a signal event
我檢查了相關帖子,但仍然無法找到答案。 專家,請幫助我。 我基本上有兩個線程,一個線程從以太網接收數據,另一個線程處理接收到的數據。 為了獲得最佳性能,請在第ThreadRecv接收第n幀和第ThreadCompute Process(n-1)的幀。 我記錄了時序關系,發現如果事件在等待功能之前發出信號,它將不會得到該事件。
這是粗糙的代碼:
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;
}
該程序將記錄時間,部分輸出將如下所示:
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
第一列是ping編號,第二列是不相關的,第三列是ThreadCompute的絕對時間,第四列是ThreadCompute的持續時間,第五列是不釋放的,第六列是ThreadRecv,第七列是threadRecv的持續時間。 請注意,我們得到了兩個相同的輸出,其ping號為200。這表明threadrecv比ThreadCompute慢一點。 recvStart的發布要早於Wait函數,並且不會收到它。
這是完全錯誤的設計。
WaitForSingleObject(pThread->Event_RecvDone,INFINITE);
pThread->Event_RecvStart.SetEvent(); //let recv start at the same time as computing
您等待接收到一個數據包(由ping_num標識),並告訴Receiver線程繼續接收, 然后開始處理該數據包。 在計算線程完成對剛剛接收到的數據包的處理之前 ,接收方線程可能會增加ping_num。 在多線程環境中,這是完全可能的。
我認為您應該重新設計接收/計算過程的邏輯。 最好使用列表或隊列將接收到的數據包存儲在Receiver線程中,並將其提取到Computing線程中。 當然,您必須使用Mutex或其他方式來保護列表/隊列。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.