December 12, 2006

Это вам не математика

"От перестановки мест слагаемых сумма не меняется"
переместительный закон для сложения

Не знаю, кто как, а я не раз слышал байки о том, что сложные ошибки, периодически происходящие в программных системах, лечатся каким-нибудь банальным действием, типа "поменяли местами 2 строчки кода и всё заработало". Теперь настало время и мне рассказать подобную историю.

Дело было так. Задача - обеспечить поиск работающих экземпляров приложения в локальной сети. Решение очевидно: на стороне искомого - Listener, ожидающий запросов из сети и отвечающий на них, на стороне ищущего - Screamer (ну он действительно крикун, что я сделаю :-)), посылающий широковещательный запрос в сеть и ожидающий ответов от всех Listener'ов. Всё предельно просто. Было написано, оттестировано и работало. Работало на Microsoft .Net v1.1.

Потом проект мигрировали под .Net v2.0, который много что объявил obsolete, что-то было переписано, но это совсем другая история. Внезапно оказалось, что описанное выше решение работает через раз. То есть, иногда оно видит работающие приложения, иногда нет, и даже если видит, то необязательно все. Признаться, я долгое время грешил на возможно новую реализацию всего этого механизма в .Net, а когда взялся за проблему всерьёз, понял, что был неправ.

Основная проблема скрывалась внутри Listener'а. Его ThreadProc крутился пока не выполнялось некое условие, а именно, не выставлялся флаг об остановке. Только вот при инициализации Listener'a сначала создавался и запускался тред, и только потом выставлялся флаг. Получается, что в один и тот же код в версии 2.0 работает быстрее чем в версии 1.1.

Ну и конечно, всё решилось перестановкой двух строчек, запуска треда и выставления флага. И кто бы мог подумать с такими симптомами...

Когда я поделился решением с коллегами, они, конечно, смеялись, но простили мне оплошность с невовремя установленным флагом. И вскоре я взялся за решение другой проблемы. В этот раз почему-то не всегда срабатывало получение данных из последовательного порта.  Если отправлять команду, требующую работы устройства, всё работает стопроцентно, а если посылать подряд, скажем, 1000 команд ATZ, ответ рано или поздно не приходит. Тут уж я не стал, как водится, ругаться на программистов Microsoft, а начал искать ошибку в своём коде обмена данными с портом. Логика там непростая, поэтому пришлось потратить какое-то время и огромное количество Debug.WriteLine. И что в итоге, спросите вы! Да то же самое. Я сначала посылал команду в порт и только спустя пару строчек кода подписывался на событие DataReceived. И снова всё решилось перестановкой двух "слагаемых".

Вот такая вот математика.


Comments: Post a Comment



<< Home

This page is powered by Blogger. Isn't yours?