Sleep () плохой дизайн, но, похоже, мой единственный вариант - PullRequest
7 голосов
/ 24 ноября 2011

Я пишу класс 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 );
}

Я знаю, что использование Sleep () не является хорошей практикой проектирования, но если я удаляю оператор Sleep () или даже сокращаю время, в течение которого цикл спит, то контроллер выдает ошибки о заполнении буфера и передаче выходит из строя. Есть ли лучший способ сделать это?

Прежде чем вы это скажете, нет, я не могу отправить сообщение контроллеру, чтобы определить, готов ли он к следующему пакету. У этого нет той функциональности.

Edit: Я забыл упомянуть, что интервал, в течение которого я сплю, несколько «слеп». Спецификация протокола, предоставленная производителем, не детализирует промежуток времени, необходимый между пакетами. Поэтому я должен был определить это значение методом проб и ошибок. Я боюсь, что это может не работать на каждом компьютере и более того, что это может не работать на каждом контроллере.

Эта разработка ведется для Windows XP / Vista / 7.

Правка № 2: Кроме того, количество данных в пакете на самом деле также является методом проб и ошибок. Спецификация протокола допускает пакеты размером 65 535 байт (включая заголовок). Но если вы отправляете более 129 байтов за раз, вы начинаете видеть проблемы, когда иногда это работает, а иногда нет. Также, похоже, существует связь между временем сна и количеством байтов, которые вы можете отправить. Если я уменьшу размер пакета до 20 байт на пакет, я могу уменьшить время ожидания до 400 миллисекунд. Я полагаю, что причина этих проблем связана со временем, которое требуется контроллеру для перемещения данных из его буфера в файл.

Ответы [ 3 ]

10 голосов
/ 24 ноября 2011

То, что вы делаете, называется синхронизацией вслепую.Это не обязательно плохой дизайн.Если ваше устройство не имеет функции для указания того, что оно готово для получения дополнительных данных или нет, это единственный способ сделать это.

Обычно устройства указывают максимальную скорость передачи данных или минимальный объем.времени между байтами.

Я думаю, что идея этой плохой практики исходит из случаев, когда вы выбираете значение задержки вслепую (производительность пострадает, если она больше, чем должна быть), если у вас есть лучшие методы синхронизации или еслиВы используете задержки, чтобы скрыть проблемы синхронизации (скажем, в многопоточном приложении).

2 голосов
/ 08 января 2012

Еще одна причина, по которой Sleep может быть неправильным, заключается в том, что вы можете захотеть завершить работу рано.Если вы вместо этого сделали

WaitForSingleObject(hTerminatingEvent, 600);

Вы могли бы иметь другой поток, сигнализирующий о событии, которое вы хотите завершить и завершить рано.(В этом случае этот вызов функции будет продолжаться через 600 мс, даже если событие не было сообщено.)

0 голосов
/ 08 января 2012

В Windows я бы использовал для этого таймер ожидания вместо Sleep(), но если вашему оборудованию нужны задержки, вам понадобятся задержки.

...