Почему мы не можем изменить состояние квартиры потока ThreadPool и почему мы не требуем messagepump, когда ShowDialog используется?

Недавно, я встретился с этой ситуацией, где я хотел отобразить форму на другом потоке (не основной поток / поток UI). Я использовал поток пула потоков. Форма разместила RCW (для COM-компонента). Инстанцирование формы дало мне исключение, что потоком должен быть STA. Я пытался установить состояние квартиры как STA. Но, который не работал также. Я наконец закончил тем, что создал поток явно, и это работало (я использовал ShowDialog и не должен создавать насос meesage).

Править:

  • Я знаю, что потоками пула потоков является MTA. Но, почему это не может быть установлено на STA? Просто любопытный на предмет этого.

  • Другой вопрос, который просто появился в моей голове: Почему мы не требуем насоса сообщения, когда Showdialog () (для отображения формы) используется

6
задан Spikolynn 28 November 2019 в 14:35
поделиться

2 ответа

The apartment is selected by a call to CoInitializeEx(). A thread in the thread pool has already made that call, changing the apartment after that call is not possible.

That a thread pool would choose MTA makes sense, it is after all intended as a worker thread and shouldn't be blocked by method calls that need to be marshaled. Selecting a single-threaded apartment has the additional requirement of pumping a message loop. Something you'd never expect a threadpool thread to do.

The message loop is necessary because that's the vehicle that COM uses to marshal a call made on another thread. That call has to be "injected" in the STA thread, that's only possible if the thread is in a known quiescent state. If it isn't, such a call would cause major re-entrancy problems. Which it sometimes does even if the thread is pumping the loop.

You didn't need to pump a message loop yourself with Application.Run() because ShowDialog() starts its own message loop. That's how it gains modality. That nested loop exits as soon as the dialog closes.

9
ответ дан 8 December 2019 в 13:48
поделиться

Не следует полагаться на конкретное поведение потоков пула потоков. Как правило, поток в пуле потоков может быть заменен CLR в любое время без вашего ведома. Потоки пула потоков предназначены для использования с простыми задачами, предпочтительно краткосрочными.

Если вы хотите иметь точный контроль над настройками потоков, вы должны создать выделенный поток. Настройка состояния квартиры является прекрасным примером этого.


В дополнение к приведенным выше теоретическим причинам существует практическая проблема с тем, что вы пытаетесь сделать. Размещение формы во втором потоке не работает (без большой дополнительной работы). Формы должны запускаться в том же потоке, что и насос сообщений - в противном случае они не будут получать никаких сообщений Windows и не будут обновляться должным образом.

Вы можете создать форму в отдельном потоке, если вы реализуете полный цикл сообщений для этот поток, но обычно лучше просто поместить свои рабочие элементы в фоновые потоки и использовать методы асинхронного программирования, чтобы ваш поток пользовательского интерфейса с момента времени реагировал.

8
ответ дан 8 December 2019 в 13:48
поделиться
Другие вопросы по тегам:

Похожие вопросы: