2011-11-23 22 views
7

Piszę klasę IO, aby przesłać/pobrać pliki do kontrolera przez port szeregowy RS-232. Niestety, nie mogę wysłać całego pliku naraz, muszę go rozbić na pakiety i przesłać trochę na raz. Oto podstawowe podejście ...Funkcja Sleep() jest złym projektem, ale wydaje się być moją jedyną opcją

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); 
} 

wiem, że za pomocą sleep() nie jest dobrą praktyką projektowania, ale jeśli usunąć sleep() oświadczenie lub nawet skrócić czas ilość pętli sny, wtedy sterownik zgłasza błędy związane z zapełnieniem bufora, a transfer nie powiedzie się. Czy jest lepszy sposób to zrobić?

Zanim to powiem, nie mogę wysłać wiadomości do kontrolera, aby określić, czy jest gotowy na następny pakiet. Nie ma tej funkcjonalności.

Edit „ślepy” Zapomniałem wspomnieć, że przedział, w którym mam do snu jest nieco Specyfikacja protokołu dostarczona przez producenta nie określa długości wymaganego czasu między pakietami. Musiałem więc ustalić tę wartość metodą prób i błędów. Obawiam się, że może nie działać na każdym komputerze, a może nie działać na każdym kontrolerze.

Ten rozwój dotyczy systemu Windows XP/Vista/7.

Edytuj nr 2: Również ilość danych w pakiecie jest w rzeczywistości próbą i błędem. Specyfikacja protokołu dopuszcza pakiety 65 535 bajtów (łącznie z nagłówkiem). Ale jeśli wysyłasz więcej niż 129 bajtów na raz, zaczynasz widzieć problemy, które czasem działają, a czasem nie. Wydaje się również, że istnieje związek między czasem snu a ilością bajtów, które możesz wysłać. Jeśli zmniejszę rozmiar pakietu do 20 bajtów na pakiet, mogę skrócić czas uśpienia do 400 milisekund. Uważam, że przyczyną tych problemów jest czas potrzebny na przeniesienie danych z bufora do pliku przez kontrolera.

+0

Czy zawsze otrzymujesz odpowiedź od kontrolera? – dwo

+6

Jeśli twoje wymagania sprzętowe obejmują wysyłanie tak wielu bajtów na raz, a następnie czekają tyle milisekund, nie ma oczywiście lepszego sposobu na jego wdrożenie. – Gabe

+1

Tak, powiedziałbym nawet, że używanie snu nie jest takie złe. Przypuszczam, że mógłbyś napisać fantazyjną funkcję obejmującą , ale biorąc pod uwagę twoje warunki, Sleep() brzmi rozsądnie. – ScarletAmaranth

Odpowiedz

10

To, co robisz, nazywa się synchronizacją w ciemno. To niekoniecznie zły projekt. Jeśli twoje urządzenie nie ma funkcji informującej o tym, że jest gotowe na więcej danych, to jest to jedyny sposób na zrobienie tego.

Urządzenia często określają maksymalną szybkość transmisji danych lub minimalny odstęp czasu między bajtami.

Myślę, że pomysł na to, że jest to zła praktyka, pochodzi z przypadków, w których ślepo wybierasz wartość opóźnienia (wydajność będzie większa, niż jest wymagana), jeśli masz lepsze metody synchronizacji, lub jeśli jesteś korzystanie z opóźnień, aby ukryć problemy z synchronizacją (powiedzmy, w aplikacji wielowątkowej).

+0

O wiele więcej informacji na temat kontrolera to wyczyści. – dbasnett

+0

Proszę zobaczyć moje zmiany, aby uzyskać więcej informacji. –

2

Kolejny powód Uśpienie może nie być właściwe, możesz chcieć, aby funkcja została wcześniej zamknięta. Jeśli zamiast tego możesz mieć inny wątek, zdarzenie, które chcesz zakończyć i zakończyć wcześnie, możesz uzyskać inny wątek. (W takim przypadku wywołanie funkcji będzie kontynuowane po 600 ms, nawet jeśli zdarzenie nie zostanie zasygnalizowane).

0

W systemie Windows używałbym do tego czasu sprawdzanego timera zamiast Sleep(), ale jeśli sprzęt wymaga opóźnień, to będziesz potrzebować opóźnień.

Powiązane problemy