Как определить, находимся ли мы в потоке пользовательского интерфейса?
Для аргумента рассмотрим поток пользовательского интерфейса как поток, который имел вызов Application.Run()
или один из них, вызывающий его, и имеет активный цикл сообщений.
Есть ли способ обнаружения, если мы в настоящее время выполняем такой поток?
Причина, по которой я хочу, это потому, что у меня есть класс с частной функцией, которая работает долго. Сам класс уже многопоточен, и использование этого класса таково, что его можно использовать либо из пользовательского интерфейса, либо из фоновых потоков, выполняющих обработку. Эта функция также попадает в эту сеть. Но я не хочу, чтобы он блокировал поток пользовательского интерфейса. Поэтому я хочу определить, работает ли я в потоке пользовательского интерфейса, и если да, то перепрограммируйте вызов функции в фоновый поток (возможно, ThreadPool
, но это не проблема для этого обсуждения). Это вполне корректно, но фоновые потоки, вероятно, полагаются на вывод функции, поэтому блокировка для них лучше, тогда как поток пользовательского интерфейса обращается к нему более "заново" и "забывает".
Ответы
Ответ 1
Я бы предположил, что это решение, которое должен сделать вызывающий. Вы всегда можете написать методы-обертки, чтобы упростить его, но это означает, что у вас не будет проблем с тем, что вызывающий объект находится в "странной" ситуации (например, инфраструктура пользовательского интерфейса, о которой вы не знаете, или что-то еще с циклом события), и вы принимаете для них неправильное решение.
Если метод когда-либо должен обеспечивать обратную связь в правильном потоке, я бы прошел через ISynchronizeInvoke
(реализованный Control
), чтобы сделать это с помощью агностического интерфейса.
Ответ 2
Если у вас есть доступ к Form
или Control
, вы можете проверить свойство InvokeRequired
; это вернет false
, если вы находитесь в потоке пользовательского интерфейса и true
, если это не так. Если это происходит в контексте, где вы не можете проверить с помощью Control
, вы можете легко установить статическое свойство в своей программе что вы можете проверить. Сохраните ссылку на Thread.CurrentThread
при запуске и сравните Thread.CurrentThread
с этой ссылкой, когда вам нужно знать:
static class Program
{
private static Thread _startupThread = null;
[STAThread]
static void Main()
{
_startupThread = Thread.CurrentThread;
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
public static bool IsRunningOnStartupThread()
{
return Thread.CurrentThread == _startupThread;
}
}
Вызывая Program.IsRunningOnStartupThread
, вы получите сообщение bool
, если вы есть.
Ответ 3
bool isMessageLoopThread = System.Windows.Forms.Application.MessageLoop;
Ответ 4
См. Обнаружение работы в главной теме в библиотеке С#