Я думаю, что наилучшее решение во многом зависит от требований вашего приложения и характера вашего соединения.В простейшем случае то, что вы описываете в (1), вероятно, будет адекватным.
Лично я почти всегда помещаю связи в отдельный поток.Это немного сложнее, но может дать существенные преимущества в скорости и гарантирует, что ваш пользовательский интерфейс не перестает отвечать на запросы, когда что-то странное происходит в коммуникациях (например, от USB-кабеля)
Дизайн, который я использовалчаще всего (RS232 Comms) используется небольшое изменение того, что вы описываете в (1).У меня есть класс CComms в качестве члена моего основного объекта приложения, который создает поток для запуска связи. Затем у меня есть очень простая система сообщений, похожая на ту, которую использует Windows, которая обрабатывает синхронизацию всех потоков, передавая данные между потоком связи.и основное приложение.Основное приложение имеет несколько простых функций для отправки сообщений от других классов и отправки ответов обратно в соответствующий класс.
Надеюсь, это немного поможет ...