Принудительное выполнение кода в основном потоке - PullRequest
6 голосов
/ 25 апреля 2009

Как я могу заставить часть кода выполняться в моем основном потоке?

Вот почему я хотел бы знать:

У меня есть пользовательское окно сообщения, которое иногда отображается из потока, который не является основным потоком. Однако, когда вызывается конструктор окна сообщения, я получаю исключение InvalidOperationException, говорящее: «Вызывающий поток должен быть STA, потому что это требуется для многих компонентов пользовательского интерфейса». Это имеет смысл, элементы пользовательского интерфейса должны обрабатываться в основном потоке.

Моя функция MessageBox.ShowMessage (...) - это статическая функция, которая создает экземпляр моего настраиваемого окна сообщения и показывает его. Есть ли что-то, что я мог бы добавить в ShowMessage, что заставило бы окно сообщения быть созданным и показанным в главном потоке? В другом месте моего кода я использую Control.BeginInvoke для решения подобных проблем, но, поскольку это статическая функция, для меня не существует уже существующего элемента пользовательского интерфейса для вызова BeginInvoke.

Нужно ли вызывать MessageBox.ShowMessage с помощью Control.BeginInvoke? Я бы предпочел, чтобы BeginInvoke (или некоторый эквивалент) вызывался из ShowMessage.

Ответы [ 3 ]

5 голосов
/ 25 апреля 2009

Ваше мышление правильное - для того, чтобы заставить его работать должным образом, вам нужно будет вызвать его из основного потока.

Самый простой способ? Когда вы запускаете основную форму, сохраняйте ссылку в статической переменной, видимой для вашего вызова ShowMessage (). Затем ваш ShowMessage может сделать стандарт:

if(myForm.InvokeRequired)
{
     myForm.Invoke(() => ShowMessage(arg1,arg2,arg3));
     return;
}
.... other code here....
5 голосов
/ 25 апреля 2009

Здесь есть несколько вариантов:

  • сделать второй поток STA (вы можете сделать это только для своих Thread - не для ThreadPool потоков) - через .SetApartmentState(ApartmentState.STA);
  • посмотреть, не является ли SynchronizationContext.Current ненулевым; если это так, используйте Send / Post
  • передать форму / элемент управления как экземпляр ISynchronizeInvoke (может не относиться к WPF - я не уверен на 100%)
1 голос
/ 25 апреля 2009

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...