Как определить, находимся ли мы в потоке пользовательского интерфейса? - PullRequest
13 голосов
/ 19 июля 2009

В качестве аргумента рассмотрим поток пользовательского интерфейса как поток, которому был вызван Application.Run() или вызвана одна из его перегрузок, и запущен активный цикл обработки сообщений.

Есть ли способ определить, выполняем ли мы в данный момент такой поток?

Причина, по которой я этого хочу, в том, что у меня есть класс с закрытой функцией, которая работает долго. Сам класс уже многопоточный, и использование этого класса таково, что его можно использовать либо из пользовательского интерфейса, либо из фоновых потоков, выполняющих обработку. Эта функция также попадает в эту сеть. Но я не хочу, чтобы это блокировало поток пользовательского интерфейса. Поэтому я хочу определить, запущен ли я в потоке пользовательского интерфейса и, если это так, раскошелиться на вызов функции в фоновом потоке (вероятно, ThreadPool, но это не проблема для этого обсуждения). Это вполне корректно, но фоновые потоки, вероятно, полагаются на выходные данные функции, поэтому блокировка для них лучше, в то время как поток пользовательского интерфейса обращается к ней более «установил и забыл».

Ответы [ 4 ]

12 голосов
/ 19 июля 2009

Если у вас есть доступ к 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 сообщение о том, есть вы или нет.

8 голосов
/ 13 ноября 2009

bool isMessageLoopThread = System.Windows.Forms.Application.MessageLoop;

7 голосов
/ 19 июля 2009

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

Если метод когда-либо должен обеспечивать обратную связь в нужном потоке, я бы передал ISynchronizeInvoke (реализовано Control), чтобы сделать это независимым от пользовательского интерфейса способом.

6 голосов
/ 19 июля 2009
...