SpeechRecognitionEngine - это оболочка для COM-сервера с многопоточным подключением. Да, для них жестким требованием является как минимум один поток, который является STA и прокачивает цикл сообщений. Поскольку вы пишете библиотеку, вы не можете контролировать то, что выбирает ваш клиент. Но вы можете сказать ей, что есть проблема, а не просто тупик вашего распознавателя речи. Добавьте эту проверку в ваш конструктор класса:
if (System.Threading.Thread.CurrentThread.GetApartmentState() !=
System.Threading.ApartmentState.STA) {
throw new InvalidOperationException("UI thread required");
}
Проверка немного сложна, распознаватель все равно будет работать, если он создан в рабочем потоке в программе, которая также имеет поток пользовательского интерфейса. Хотя этот режим совершенно нежелателен, каждый отдельный вызов распознавателя будет маршалироваться, а любые генерируемые вами события должны маршалироваться клиентом. Я бы предложил аргумент вашему конструктору основного класса, который позволяет клиенту указать, что он действительно хочет, чтобы распознаватель работал в потоке.