2011-11-23 24 views
7

我正在編寫一個IO類,通過RS-232串行將文件上載/下載到控制器。不幸的是,我無法一次發送整個文件,我不得不將它分解成數據包並一次發送一次。這裏的基本方法...睡眠()是一個糟糕的設計,但似乎是我唯一的選擇

ifstream file ("path/to/file.ext", ios::in | ios::binary); 

while(!file.eof()) 
{ 
    //... zero buffer, and add packet header (8 bytes) 
    size_t nResult = file.read(&buffer[8], 129); 
    Serial.Write(buffer, nResult+8); 
    //... see if controller wrote anything to the serial port and process it's command 
    Sleep(600); 
} 

我知道,使用睡眠()是不是一個好的設計,但如果我刪除了睡眠()語句甚至縮短時間量的循環休眠,則控制器拋出關於緩衝區已滿的錯誤,並且傳輸失敗。 有沒有更好的方法來做到這一點?

在你說出來之前,我不能發送消息給控制器,以確定它是否準備好接受下一個數據包。它沒有這個功能。

編輯: 我忘了提,我不得不睡在哪個區間是有點「盲目」。製造商提供的協議規範沒有詳細說明數據包之間所需的任何時間長度。所以我必須通過反覆試驗來確定這個價值。我擔心它可能無法在每臺PC上運行,因此它可能無法在每個控制器上運行。

該開發工作正在爲Windows XP/Vista/7完成。

編輯#2: 此外,每個數據包的數據量實際上也是一個試錯法猜測。協議規範允許包含65,535字節的數據包(包括頭部)。但是,如果您一次發送超過129個字節,您會發現問題有時會起作用,有時不起作用。睡眠時間和可以發送的字節數量之間似乎也有關係。如果我將數據包大小降低到每個數據包20個字節,我可以將睡眠時間降低到400毫秒。我相信造成這些問題的原因是控制器將數據從緩衝區移動到文件的時間。

+0

你總是從控制器得到答案嗎? – dwo

+6

如果您的硬件需求包括一次發送如此多的字節,然後等待那麼多毫秒,那麼實現它的方式並不明顯。 – Gabe

+1

是的,我甚至會認爲使用睡眠不是一個想法的壞處。我想你可以寫一個奇特的函數,包括,但考慮到你的條件,Sleep()聽起來很合理。 – ScarletAmaranth

回答

10

你在做什麼叫盲循環同步。這不一定是壞設計。如果您的設備沒有指示它已準備好接收更多數據的功能,則這是執行此操作的唯一方法。

設備通常指定最大數據速率或最小字節間時間量。

我認爲這是一個不好的做法的想法來自盲目選擇延遲值的情況(如果它比所需要的大,性能會受到影響),如果您有更好的同步方法可用,或者如果您使用延遲來掩蓋計時問題(例如,在多線程應用程序中)。

+0

有關控制器的更多信息將清除此問題。 – dbasnett

+0

請參閱我的編輯以獲取更多信息。 –

2

睡眠可能不正確的另一個原因是您可能希望功能提前退出。如果您改爲

WaitForSingleObject(hTerminatingEvent, 600); 

您可以讓另一個線程發出要退出並提前終止的事件。 (在這種情況下,即使事件未發出信號,該函數調用仍將在600 ms後繼續)。

0

在Windows上,我使用等待定時器來代替Sleep(),但如果您的硬件需要延遲,那麼你將需要延遲。

相關問題