2011-11-23 4 views
7

Estoy escribiendo una clase IO para cargar/descargar archivos en un controlador a través de una serie RS-232. Desafortunadamente, no puedo enviar todo un archivo de una vez, tengo que dividirlo en paquetes y enviarlo un poco a la vez. Aquí está el enfoque básico ...Sleep() es un mal diseño, pero parece ser mi única opción

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

Yo sé que el uso de Sleep() no es una buena práctica de diseño, pero si quito la declaración del sueño() o incluso acortar la cantidad de tiempo del bucle duerme, entonces el controlador arroja errores sobre que el búfer está lleno y la transferencia falla. ¿Hay una mejor manera de hacer esto?

Antes de decirlo, no, no puedo enviar un mensaje al controlador para determinar si está listo para el siguiente paquete. No tiene esa funcionalidad.

Editar: me olvidó mencionar que el intervalo en el que estoy teniendo un poco de sueño es "ciego". La especificación de protocolo proporcionada por el fabricante no detalla el tiempo necesario entre los paquetes. Así que tuve que determinar ese valor por prueba y error. Me temo que puede no funcionar en todas las PC y más para que no funcione en todos los controladores.

Este desarrollo se está realizando para Windows XP/Vista/7.

Edit # 2: Además, la cantidad de datos por paquete es también una prueba y error. La especificación del protocolo permite paquetes de 65.535 bytes (incluido el encabezado). Pero si envía más de 129 bytes a la vez, comienza a ver problemas en los que a veces funciona y otras veces no. También parece haber una relación entre el tiempo que tiene para dormir y la cantidad de bytes que puede enviar. Si reduzco el tamaño del paquete a 20 bytes por paquete, puedo reducir el tiempo de inactividad a 400 milisegundos. Creo que la razón de estos problemas se deriva del tiempo que le lleva al controlador mover los datos de su búfer al archivo.

+0

¿Siempre recibe una respuesta del controlador? – dwo

+6

Si sus requisitos de hardware incluyen enviar tantos bytes a la vez y luego esperar tantos milisegundos, no hay una forma obviamente mejor de implementarlo. – Gabe

+1

Sí, incluso diría que usar sueño no es una mala idea. Supongo que podría escribir una función elegante que incluya pero, dadas sus condiciones, Sleep() suena razonable. – ScarletAmaranth

Respuesta

10

Lo que está haciendo se llama sincronización de ciclo ciego. No es necesariamente un mal diseño. Si su dispositivo no tiene la funcionalidad para indicar que está listo para más datos o no, esta es la única forma de hacerlo.

Es común que los dispositivos especifiquen una velocidad de datos máxima o una cantidad mínima de tiempo entre bytes.

Creo que la idea de que esto sea una mala práctica proviene de casos en los que elige ciegamente un valor de retraso (el rendimiento sufrirá si es mayor de lo que necesita), si tiene mejores métodos de sincronización disponibles, o si utilizando demoras para cubrir problemas de tiempo (por ejemplo, en una aplicación multiproceso).

+0

Mucha más información sobre el controlador aclararía esto. – dbasnett

+0

Consulte mis ediciones para obtener más información. –

2

Otra razón por la que dormir puede no ser lo correcto es que es posible que desee que la funcionalidad se cierre antes. Si en su lugar lo hizo

WaitForSingleObject(hTerminatingEvent, 600); 

Puede tener otro subproceso que indique el evento que desea cerrar y terminar antes. (En este caso, esta llamada de función continuará después de 600 ms incluso si el evento no se señaliza.)

0

En Windows, utilizaría un temporizador de espera para esto en lugar de Sleep(), pero si su hardware necesita retrasos, entonces vas a necesitar retrasos.

Cuestiones relacionadas