2009-07-19 6 views
13

Dla dobra argumentu rozważ wątek UI jako wątek, który miał wywołanie Application.Run() lub jeden z jego przeciążeń wywołał go i uruchomił aktywną pętlę komunikatów.Jak wykryć, czy jesteśmy w wątku UI?

Czy istnieje sposób na wykrycie, czy obecnie wykonujemy pracę w takim wątku?

Powodem, dla którego tego chcę, jest to, że mam klasę z prywatną funkcją, która długo działa. Sama klasa jest już wielowątkowa, a użycie tej klasy jest takie, że może być używane z interfejsu lub z wątków działających w tle. Ta funkcja również wpada w tę sieć. Ale nie chcę, aby blokował wątek interfejsu użytkownika. Dlatego chcę wykryć, czy uruchamiam wątek interfejsu użytkownika, a jeśli tak, rozwiąż wywołanie funkcji w wątku tła (prawdopodobnie ThreadPool, ale to nie jest problem dla tej dyskusji). Jest to całkowicie dobrze zachowane, ale wątki w tle prawdopodobnie opierają się na wyjściu funkcji, więc blokowanie ich jest lepsze, podczas gdy wątek UI uzyskuje dostęp do niego w sposób bardziej "zapamiętywania".

Odpowiedz

7

sugeruję, że jest to rodzaj decyzji wywołujący powinien zrobić. Zawsze możesz pisać metody owijania, aby było to łatwiejsze, ale oznacza to, że nie będziesz miał problemów z tym, że osoba dzwoniąca jest w "dziwnej" sytuacji (np. Struktura interfejsu użytkownika, o której nie wiesz, lub coś innego z pętlą zdarzeń) i podejmujesz złą decyzję dla nich.

Jeśli metoda zawsze musi dostarczyć informację zwrotną w odpowiednim wątku, powinienem podać ISynchronizeInvoke (zaimplementowany przez Control), aby to zrobić w sposób niezależny od interfejsu użytkownika.

12

Jeśli masz dostęp do Form lub Control, możesz sprawdzić właściwość InvokeRequired; to powróci false, jeśli jesteś w wątku UI i true, jeśli nie jesteś. Jeśli zdarzy się to w kontekście, w którym nie możesz sprawdzić przeciwko Control, możesz łatwo ustawić nieruchomą własność w swoim programie, którą możesz sprawdzić. Przechowywać odniesienie do Thread.CurrentThread przy starcie i porównać Thread.CurrentThread do tego odniesienia, gdy trzeba wiedzieć:

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; 
    } 
} 

Dzwoniąc Program.IsRunningOnStartupThread dostaniesz bool mówiąc, jeśli jesteś lub nie.

+0

Ładowanie uruchamiane niekoniecznie jest wątkiem GUI lub jedynym wątkiem GUI. –

+1

NIEPRAWIDŁOWE: InvokeRequired zwraca true, jeśli jest na "innym wątku niż ten, dla którego utworzono formant" –

+1

@Rico: Tak, oczywiście. Nie mogę uwierzyć, że literówka od trzech lat siedzi tam i nikogo nie zauważa. Dzięki za złapanie go, zaktualizowałem odpowiedź odpowiednio. –

8

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

+0

To jest najprostsza odpowiedź dla moich celów. – ToolmakerSteve

Powiązane problemy