Как определить, находимся ли мы в потоке пользовательского интерфейса?

Для аргумента рассмотрим поток пользовательского интерфейса как поток, который имел вызов 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;