2012-07-10 18 views
14

Chyba potrzebuje pomocy ze zrozumieniem Dispatcher kolejki.Zrozumienie dyspozytor Kolejka

Kiedy nadejdzie nowa praca zostanie dodana na początku kolejki dyspozytora i kiedy dyspozytor chce przetwarzać element roboczy to zostanie usunięty z początku.

W bardziej ogólnych kategoriach: Jeśli jest praca, zostaje zapisana w sposób FIFO wewnątrz kolejki i przetwarzana tak długo, jak długo nie ma już pracy.

dokumentacji MSDN here odnosi się do loop i frame:

The Dispatcher processes the work item queue in a loop. The loop is referred to as a frame.

Ale gdzie jest pętla w tym kontekście? Dla mnie pętla jest czymś, co iteruje nad czymś, a kiedy dociera do końca, zaczyna się od nowa.

A jaka jest koncepcja frame? Według dokumentacji MSDN ramka jest uderzeniem elementów roboczych wewnątrz kolejki? Jeśli to prawda, jak należy zastosować metodę statyczną?

Najciekawsze pytanie brzmi: czy istnieje sposób na uzyskanie aktualnego stanu kolejki, szczególnie, ile elementów znajduje się w kolejce.

Czy trzymać jeśli to metoda, która została wywołana przed (i do nich umieścić w kolejce Dispatcher) zostanie wykonany, że jest następnie usuwany z kolejki natychmiast, czy też trwać wewnątrz na kolejny okres czasu?

wiem, Tak wiele pytań :-)

+1

pierwsze pytanie: dlaczego? Dlaczego chcesz coś z Dispatcherem? Zazwyczaj Dispatcher jest po prostu "pompą komunikatów" dla procesu WPF. Obsługuje wszystkie komunikaty/zdarzenia/polecenia za pośrednictwem interfejsu użytkownika WPF do kodu aplikacji (np. Ruchy myszki, kliknięcia itp.) Gdy wywoływana jest metoda uruchamiania aplikacji, wywołuje PushFrame, aby uruchomić tę pętlę. Nie możesz uruchomić kolejnego dla tego samego wątku; i Dispatcher ma na celu przetwarzanie pracy interfejsu użytkownika. –

+2

Czy przeczytałeś o [modelu wątków] (http://msdn.microsoft.com/en-us/library/ms741870.aspx)? –

+1

Jest to standardowe rozwiązanie problemu producent-konsument: http://en.wikipedia.org/wiki/Producer-consumer_problem –

Odpowiedz

22

Jest bardzo mało dokumentacji otaczający Dispatcher, więc trzeba będzie rozbierać się trochę wiedzieć na temat wewnętrznych mechanizmów.

Dyspozytor jest w zasadzie czymś, co wykonuje pracę wokół aplikacji Message Pump. Ten, o którym mowa, znajduje się na szczycie windows message loop.

W konsekwencji, nie może być tylko jedna aplikacja Dyspozytor - globalna dyspozytor obiektu dojechać Application.Current.Dispatcher. Inne dyspozytorzy są możliwe dzięki dostępowi Dispatcher.CurrentDispatcher, które zgodnie z dokumentacją

Pobiera dyspozytor dla wątku aktualnie wykonującego i tworzy nowy Dispatcher jeśli ktoś nie jest już związany z wątku.

Jednak wywołanie Run w nowym dyżurującym będzie blokowane.

Po wykonaniu Dispatcher.PushFrame, to w zasadzie wypycha klatkę na obecnym dyspozytora. Wszystko, co odziedziczy po DispatcherObject, takie jak DispatcherFrame, spowoduje, że jego moduł rozsyłający zostanie ustawiony na bieżący. Możemy to sprawdzić, patrząc na jego konstruktora.

private Dispatcher _dispatcher; 

protected DispatcherObject() 
{ 
    this._dispatcher = Dispatcher.CurrentDispatcher; 
} 

Oczywiście, mając prostą pętlę zdarzeń nie wystarczy - są takie chwile, kiedy trzeba obalić obecną pętlę zdarzeń, aby zmusić innych do zrobienia. I dlatego masz DispatcherFrame.To właśnie stanowi pętlę zdarzeń. Po naciśnięciu ramkę do dyspozytora, to co się dzieje:

while (frame.Continue) 
     { 
      if (!this.GetMessage(ref msg, IntPtr.Zero, 0, 0)) 
      { 
       break; 
      } 
      this.TranslateAndDispatchMessage(ref msg); 
     } 

Jest w TranslateAndDispatchMessage że priorytet kolejki w Dyspozytora zostanie ocenione, po wiadomość jest wyjęty.

Jeśli operacja trwa długo biec od dyspozytora, że ​​chwilowo zatrzymuje pętlę zdarzeń i dlatego, że nie reaguje na sygnalizację, aplikacja wydaje się, że przestaje odpowiadać.

Here's an article które wykorzystuje w celu wymuszenia interfejsu w odpowiedzi umożliwiając pętla wydarzenie prowadzony krótko.

W celu uzyskania dostępu do kolejki, jak to jest, nie ma sposobu, aby poznać stan kolejki poza dyspozytora. To jest wewnętrzny szczegół i rozsądne jest, że nie jest on odsłonięty.

+1

Dziękuję bardzo za szczegółową odpowiedź (i przepraszam za opóźnienie). –

+1

@Marc Bez problemu. :) – Asti

+6

_ "W związku z tym, może być tylko jeden Dispatcher na aplikację." _. <= To nie jest prawda, instancje dispatchera będą związane wątkami. Zobacz podsumowanie Dispatchera.CurrentDispatcher: _ "Pobiera dla aktualnie wykonywanego wątku i tworzy nowy, jeśli nie jest już powiązany z wątkiem." _ Możesz sobie wyobrazić, że Dispatcher jako rozszerzenie do messagepump, rozszerzenie pozwala na wykonanie deleguje zamiast obsługiwać tylko kodów wiadomości. –