Как определить, находимся ли мы в потоке UI?
для аргумента рассмотрим поток пользовательского интерфейса как поток, у которого был вызов Application.Run()
или одна из его перегрузок вызывается на нем и имеет активный цикл сообщений.
есть ли способ определить, выполняем ли мы в данный момент такой поток?
причина, по которой я хочу этого, заключается в том, что у меня есть класс с частной функцией, которая работает долго. Сам класс уже многопоточен, и использование этого класса таково, что его можно использовать из любого пользовательский интерфейс или из фоновых потоков, выполняющих обработку. Эта функция также попадает в эту сеть. Но я не хочу, чтобы он блокировал поток пользовательского интерфейса. Поэтому я хочу определить, работаю ли я в потоке пользовательского интерфейса, и если да, то разветвите вызов функции в фоновый поток (вероятно,ThreadPool
, но это не проблема для этой дискуссии). Это полностью хорошо себя ведет, но фоновые потоки, вероятно, полагаются на вывод функции, поэтому блокировка для них лучше, тогда как поток пользовательского интерфейса обращается к нему в больше манеры "установить и забыть".
4 ответов
Я бы предположил, что это такое решение, которое должен принять вызывающий. Вы всегда можете написать методы обертки, чтобы сделать это проще , но это означает, что у вас не будет проблем с вызывающим абонентом в "странной" ситуации (например, фреймворк пользовательского интерфейса, о котором вы не знаете, или что-то еще с циклом событий), и вы принимаете неправильное решение для них.
Если метод когда-либо должен обеспечивать обратную связь в правильном потоке, я бы передал ISynchronizeInvoke
(исполнитель Control
), чтобы сделать это в UI-агностический способ.
если у вас есть доступ к 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;
}
}
By зову Program.IsRunningOnStartupThread
вы получаете bool
говорите, если вы или нет.