2010-02-20 3 views
6

Mam silnik kodu, który odtwarza długie pliki WAV, grając mniejsze kawałki po kolei przy użyciu metod waveOutOpen i waveOutWrite API. Aby zaktualizować mój interfejs podczas odtwarzania pliku, z funkcji wywołania zwrotnego po zakończeniu odtwarzania każdego buforu I Wywołaj osobny wątek (ponieważ chcesz wykonać jak najmniej funkcji wewnątrz funkcji wywołania zwrotnego), która wywołuje metodę w moim formularzu.Jak długi jest czas opóźnienia między Control.Invoke() a wywołaniem jego Delegata?

Formularz zawiera poziom klasy EventHandler, który obsługuje metodę, w ramach której aktualizuję elementy interfejsu użytkownika o nowe informacje. W metodzie formie zwanej z funkcji zwrotnej waveOutWrite używam metody Invoke tak:

if (_updatedisplay == null) 
{ 
    // UpdateDisplay contains code to set control properties on the form 
    _updatedisplay = new EventHandler(UpdateDisplay); 
} 
Invoke(_updatedisplay); 

Everythings działa, ale wydaje się, że raz na jakiś czas jest zauważalne opóźnienie lub opóźnienie w aktualizacji UI elementy. Łatwo to zauważyć, ponieważ używam metody UpdateDisplay do kierowania animacją, więc opóźnienia pojawiają się jako "czkawka", gdzie sprite wydaje się zamarzać na ułamek sekundy, zanim przeskoczy do oczekiwanej pozycji.

Czy jest możliwe, że czasami występuje długa (może 10-15 milisekundowa) zwłoka w komunikacji krzyżowej w ten sposób? Jeśli tak, jaki jest lepszy sposób obsługi czegoś takiego?

Aktualizacja: przy okazji, jestem zdecydowanie nie pewność, że Invoke jest winowajcą tutaj. Inną możliwością jest opóźnienie pomiędzy momentem zakończenia odtwarzania dźwięku a wywołaniem funkcji wywołania zwrotnego.

Aktualizacja 2: na itowlson jest sugestii, że stosuje się System.Diagnostics.Stopwatch do odniesienia opóźnienie pomiędzy Invoke i sposobu połączenia. Z 1156 pomiarów uzyskałem 1146 przy 0 ms, 8 przy 1 ms i 2 przy 2 ms. Myślę, że można bezpiecznie powiedzieć, że nie jest to mój winowajca.

Odpowiedz

3

Tak, może występować dowolnie duże opóźnienie. Wywołaj pracę, wysyłając wiadomość systemu Windows do kontrolki docelowej, więc będzie ona przetwarzana tylko wtedy, gdy wątek docelowy będzie pompował wiadomości. Jeśli wątek przetwarza już komunikat, a przetwarzanie zajmuje trochę czasu, może nastąpić znaczne opóźnienie, zanim wątek przepompuje następny komunikat i przetworzy w ten sposób wywołanie.

Lepszym sposobem może być wywołanie BeginInvoke. Nie zapobiega to potencjalnemu opóźnieniu wątku interfejsu użytkownika przetwarzającego komunikat, ale powoduje, że wątek wywołujący nie jest blokowany podczas oczekiwania na wątek interfejsu użytkownika do przesyłania komunikatów. Jednak może to nie pomóc w scenariuszu, w którym brzmi to jak zajęcie wątku interfejsu użytkownika, który powoduje zakłócenia w animacji.

Update w odpowiedzi na Twój aktualizacji: Uwaga Mówię tutaj jest to, że mógłby być dowolnie długie opóźnienie, że nie będzie tam być zauważalne opóźnienie lub że jest to z pewnością przyczyną twoje opóźnienie. 10-15ms wydaje się niezwykle długim czasem na aplikację do przetworzenia wiadomości, chyba że w wątku UI dzieje się coś naprawdę intensywnego, więc z pewnością warto rozważyć alternatywne przyczyny!

+0

Po prostu próbowałem używać BeginInvoke, ale nadal jest czkawka. Ponadto pojawia się ten sam problem, gdy próbuję uruchomić animację z oddzwanianiem z timera hi-res i mam ten sam rodzaj usterki. Zastanawiam się, czy to jest coś podstawowego z .NET UIs? – MusiGenesis

+2

Nie, to jest fundamentalne dla * jakiegokolwiek * UI przynajmniej w zakresie działania systemu Windows. Architektura wiadomości w Windows Forms nie jest niczym nowym, tak samo działa nawet aplikacja C++ w systemie Windows.Jeśli próbujesz zaktualizować pasek postępu lub coś, czego nie powinieneś wywoływać w wątkach. Zamiast tego należy używać zapisów z blokadą do zmiennej postępu, którą wątek interfejsu użytkownika odczytuje w określonych odstępach czasu. – Josh

+0

To * brzmi * jak * być może * komponent animacji nie jest dobrym obywatelem pod względem pompowania wiadomości, ale nie zamierzam spekulować na temat tego, co się tutaj dzieje, zwłaszcza, że ​​nie masz pewności, czy to Wyzwanie. Spróbuj uchwycić czas, w którym BeginInvoke został wywołany i kiedy uruchomiono UpdateDisplay: to może pomóc w ustaleniu, czy wywołanie w wątku krzyżowym jest rzeczywiście problemem. (Będziesz musiał używać taktów high-res.) – itowlson

Powiązane problemy