2011-08-05 70 views
0

我正在用C++編寫一個程序,使用WINAPI監視某個目錄是否到達新文件,並以特定順序發送它們。這些文件來源於一個實時視頻流,因此一個單元中有2個文件 - 音頻文件和視頻文件,並且單元應按順序發送。一個。 ķ。一個。 (1.mp3,1.avi); (2.MP3,2.avi)...架構是:長期運行CreateThread故障

1)檢測到一個新的文件添加到文件夾,插入文件名輸入隊列

2)文件組織到單位,插入單位爲單元隊列

3)單位

發送單元,但是,因爲我已經使用的文件監控文件目錄添加那裏,我需要確保該文件是齊全,。 ķ。一個。它已準備好發送,因爲信號在文件創建時出現,但尚未填充信息並關閉。因此,當隊列中有超過1個文件(又名爲下一個文件創建的信號,意味着先前的文件已準備好發送)或超時(10秒)時,我會從輸入隊列中彈出文件名,因此任何文件都應該做完了。

所以一般來說這個程序運行並正常工作。但是,如果我假設發送過程需要很長時間,那麼單元隊列將會增長。在單位隊列中緩衝一些單位後,會出現該錯誤。

time[END] = 0; 
    time[START] = clock(); 
    HANDLE hIOMutex2= CreateMutex (NULL, FALSE, NULL); 
     WaitForSingleObject(hIOMutex2, INFINITE); 
     hTimer = CreateThread(NULL, 0, Timer, time, 0, &ThreadId1); 
     if(hTimer == NULL) 
      printf("Timer Error\n"); 
    ReleaseMutex(hIOMutex2); 
    ReadDirectoryChangesW(hDir, szBuffer, sizeof(szBuffer)/sizeof(TCHAR), FALSE, FILE_NOTIFY_CHANGE_FILE_NAME, &dwBytes, NULL, NULL); 
    HANDLE hIOMutex= CreateMutex (NULL, FALSE, NULL); 
     WaitForSingleObject(hIOMutex, INFINITE); 
     time[END] = clock(); 
     TerminateThread(hTimer, 0); 
    ReleaseMutex(hIOMutex); 

約800單位在隊列的緩存後,我的程序給我「時代錯誤」消息,如果我是正確的,這意味着該項目無法分配線程。但是在這段代碼中,程序完全在目錄中創建文件後終止計時器線程。所以我對這個bug感到困惑。另外有趣的是,即使有了這個時間錯誤,我的程序像往常一樣繼續發送單元,所以看起來不像操作系統錯誤或其他不同,它是錯誤的線程聲明/終止,至少對我來說似乎是這樣。 如果有幫助,還提供以下定時器代碼。

DWORD WINAPI Timer(LPVOID in){ 
clock_t* time = (clock_t*) in; 
while(TRUE){ 
    if(((clock() - time[START])/CLOCKS_PER_SEC >= 10) && (!time[END]) && (!output.empty())){ 
     Send(); 
     if(output.empty()){ 
      ExitThread(0); 
     } 
    } 
    else if((output.empty()) || (time[END])){ 
     break; 
    } 
    else{ 
     Sleep(10); 
    } 
} 
ExitThread(0); 
return 0; 
} 

請任何人在這裏給我一些建議如何解決這個錯誤?提前致謝。

+0

調用'TerminateThread()'是一個非常糟糕的主意。我不知道它是否會導致你的問題,但你不應該定期打電話。 – sharptooth

+0

嗯...有沒有其他的命令我如何終止孩子?我已經看到terminateThread()太粗糙,無法過於頻繁地調用,但我還沒有找到任何其他命令。 –

+1

您不能強行終止線程並保證安全。無論您希望線程自行結束,還是運行單獨的進程並終止後者。期望線程結束並不是那麼糟糕 - 你使用一個帶有互鎖訪問的共享變量,並且線程定期檢查該變量,並且一旦從主線程設置了另一線程退出。 – sharptooth

回答

3

在很多方面使用TerminateThread是一個壞主意。在你的情況下,它使你的程序失敗,因爲它不釋放線程堆棧的內存。如果程序使用了所有可用的虛擬內存,並且CreateThread()無法爲另一個線程保留足夠的內存,則會失敗。只有在退出程序時才使用TerminateThread。

你必須這樣做一個更聰明的方法。要麼通過請求一個線程很好地通過發信號通知某個事件退出,要麼通過僅僅消耗這種昂貴的系統資源來處理文件。一個簡單的計時器和一個線程也可以做到這一點。

+0

我不知道'TerminateThread()'沒有釋放線程的堆棧。我知道很多其他問題,但不是這個。你有任何參考? –

+0

Doh。它就在MSDN文檔的備註部分。 –