Как правило, гораздо проще взять в качестве исходной асинхронную систему и выполнять ее в синхронном режиме, чем поступать наоборот. Чтобы синхронно выполнить асинхронную систему, ваше приложение должно просто вызвать асинхронный код и начать выполнять цикл ожидания, выход из которого и выполнение дальнейшего кода осуществляются после завершения выполнения асинхронного кода. Чтобы превратить синхронное взаимодействие в асинхронное, вы должны идентифицировать все состояния приложения, которые затрагиваются коммуникационными процедурами, и создать отдельные копии этих данных, вы должны создать модель для фонового выполнения, из которой будет вызываться код, вы должны перепроектировать способ, используемый коммуникационным кодом для взаимодействия с элементами пользовательского интерфейса, поскольку организовать надежный доступ к элементам управления пользовательского интерфейса из других потоков во многих случаях невозможно (эта ошибка, несомненно снижающая надежность приложения, является весьма распространенной при использовании .NET Compact Framework! Для организации взаимодействия с элементами управления пользовательского интерфейса из других потоков следует использовать вызов метода <ЭлементУправления>.Invoke()), вы должны разработать способ уведомления пользовательского интерфейса о возникновении проблем в процессе информационного обмена, вы должны предусмотреть корректную обработку сбойных ситуаций и, наконец, вы должны разработать модель для обмена командами и состояниями между пользовательским интерфейсом и коммуникационным кодом. Сделать все это уже после того, как разработка приложения почти закончена, очень трудно, и любые попытки преобразования синхронных операций в асинхронные в мобильном приложении потребуют, по крайней мере, существенных переделок и, как правило, привнесут в ваше приложение логические ошибки и сделают его работу ненадежной. С самого начала проектируя код, с помощью которого осуществляется информационный обмен с внешними источниками информации, в асинхронной форме, вы получите намного более удовлетворительные результаты.
НА ЗАМЕТКУ
Выполнение кода в фоновом потоке обсуждается в главе 9.
Работайте на самом высоком уровне абстракции, который соответствует вашим потребностям
Как и в случае кода для настольных компьютеров и серверов, целесообразно работать на самом высоком из допустимых уровней абстракции.
Например, если в процессе работы с Internet-протоколами у вас есть возможность работать на уровне Web-служб, используя запросы/ответы SOAP, то именно так вам и следует поступить; встроенные абстракции позволят вам сэкономить массу времени, превращая ваши Web-запросы в простые вызовы методов. Если для повышения производительности приложения или в интересах его пользовательской адаптации вам необходимо спуститься вниз на один уровень, то запросы и ответы HTTP или HTTPS обеспечат вам довольно высокий уровень абстракции и, как правило, дружественность по отношению к брандмауэрам. Если окажется, что запросы/ответы HTTP не в состоянии удовлетворить ваши потребности, у вас есть возможность использовать средства коммуникации на уровне сокетов и создаваемые поверх сокетов потоки.
Работа на уровне абстракции сокетов усложняет код, поскольку для взаимодействия с серверами вам придется спроектировать собственные коммуникационные протоколы, а не использовать простые и надежно тестированные механизмы запросов/ответов HTTP. Если ваше приложение должно связываться с сервером, который требует взаимодействия на уровне сокетов, то рекомендуется рассмотреть возможность создания прокси-компонента на стороне сервера, который взаимодействовал бы с интерфейсом сокета и, в свою очередь, предоставлял вашему приложению интерфейс HTTP или Web-служб. Поскольку взаимодействие сервера с сервером обычно характеризуется более высокой надежностью по сравнению с взаимодействием между устройством и сервером, то описанная мера позволяет значительно упростить код на стороне устройства и повысить надежность вашего мобильного приложения.