Я думаю, что корень проблемы - это тесная связь между вашим анализатором пакетов и основной формой. Анализатор пакетов не должен знать ничего об активной форме или даже о том, что она вообще существует. Это усложняет обслуживание, потому что работает только в очень специфических обстоятельствах, которые уже не соответствуют действительности.
Вы можете перевернуть проблему и вызвать событие из класса, который анализирует пакеты. Это дает вам намного лучшую инкапсуляцию, потому что теперь анализатору пакетов ничего не нужно знать об остальной части приложения. Вы можете создать свои собственные аргументы событий или использовать их, например, System.Diagnostics.DataReceivedEventArgs. Затем ваша форма может поглотить событие DataReceived и вызвать свой собственный AddText для вызова обратно в основной поток, и она будет работать независимо от того, является ли форма видимой или нет.
По крайней мере, это будет работать, но это блокирующий вызов, поэтому поток анализатора пакетов будет остановлен до тех пор, пока форма полностью не обработает событие и не вернется маршализованный вызов к основному потоку. Это было бы хорошо, если скорость передачи пакетов не очень высока, но обычно вы не хотите останавливать коммуникационный поток, чтобы дождаться, пока основной поток обновит текстовое поле. Другой подход заключается в регистрации текста с использованием StringBuilder внутри анализатора пакетов и предоставлении его (накопленный текст, а не StringBuilder) через открытое для потока общедоступное свойство. Или, если вам нужно разделить отдельные сообщения, вы можете добавить их, например, в список, и иметь свойство, безопасное для потоков, возвращать массив накопленных сообщений. Тогда ваша форма может опрашивать анализатор на наличие новых зарегистрированных данных с использованием таймера с любой частотой, подходящей для вашего приложения, и только тогда, когда форма видна. Обновление не будет таким быстрым, но влияние на поток анализатора будет почти нулевым, и в целом он должен работать быстрее, если он объединяет много сообщений внутри StringBuilder или List между обновлениями, а не объединяет свойство Text с каждым отдельным пакетом.