2009-07-19 2 views
13

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

Есть ли способ обнаружить, выполняем ли мы в настоящее время такую ​​цепочку?

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

ответ

7

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

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

12

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

+0

Startupthread не обязательно является нитью графического интерфейса пользователя или единственным потоком графического интерфейса пользователя. –

+1

WRONG: InvokeRequired возвращает true, если на «другой поток, чем тот, который был создан элементом управления». –

+1

@ Rico: Да, конечно. Я не могу поверить, что опечатка сидит там последние три года, и никто не замечает. Спасибо, что поймали его, я обновил ответ соответственно. –

8

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

+0

Это самый простой ответ для моих целей. – ToolmakerSteve

Смежные вопросы