Как определить, находимся ли мы в потоке 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 говорите, если вы или нет.


bool isMessageLoopThread = система.Окна.Формы.Приложение.MessageLoop;