.NET i takie tam

Named Events – komunikacja między procesowa

with 2 comments

System Windows udostępnia nam mechanizm komunikacji między procesowej który wykorzystuje tzw. named events. Dzięki niemu możemy sygnalizować jak i monitorować, dowolnie utworzone przez nas zdarzenia np. pomiędzy dwoma różnymi programami, lub bądź chyba częściej spotykany, pomiędzy różnymi wątkami pracującymi w ramach jednej aplikacji. Ograniczeniem tego mechanizmu jest brak możliwości przekazywania danych, służy on jedynie do sygnalizacji.

Implementacja w .NET

Implementacją tego mechanizmu na platformie .NET jest klasa WaitHandle i jej pochodne jak np. EventWaitHandle. Jak to wszystko działa? Ano bardzo prosto, najpierw musimy niejako zarejestrować nasz event, przykładowo:

EventWaitHandle signal = new EventWaitHandle(false,
     EventResetMode.AutoReset, "UniqueSignalName");

Określamy czy w momencie utworzenia zdarzenia, (jest to zdarzenie tyle, że nie w .NET’owym jego sensie), powinno być ono zasygnalizowane, parametr false. Następnie określamy za pomocą EventResetMode określamy sposób pracy. Do wyboru mamy AutoReset który zaraz po naszym sygnale przywróci poprzedni stan naszego zdarzenia i ManualReset który pracuje jak jak bramka, tzn. po włączeniu wysyła sygnał tak długo aż jej sami nie zresetujemy. Ostatni parametr jest domyślny i określamy w nim nazwę naszego eventu, szczególnie przydaje się gdy planujemy komunikację między procesami które nie będą miały dostępu do referencji naszego zdarzenia (np. pomiędzy różnymi aplikacjami). Nazwa jest globalnie widoczna w systemie i każdy proces może obserwować jej zmiany, (pomijam tu kwestie związane z uprawnieniami systemu Windows) .

Tak utworzonym obiektem możemy swobodnie operować. Aby dokonać sygnalizacji korzystamy z metody Set(). W przypadku gdy EventResetMode ustatiliśmy na ManualReset aby wyłączyć ‚sygnał’ musimy skorzystać z metody Reset().

Przydatną metodą jest statyczną metoda OpenExisting klasy EventWaitHandle które umożliwia nam pobranie referencji do utworzonego przez nas zdarzenia, na podstawie jego nazwy np.:

EventWaitHandle signal =
    EventWaitHandle.OpenExisting("UniqueSignalName");

Gdy kończymy korzystać z naszego obiektu EventWaitHandle zwalniamy jego zasobu przy pomocy metody Close().

Nasłuchiwanie zmian

Niestety mechanizm ten nie został zautomatyzowany i sami musimy sprawdzić czy aby nie zaszło któreś z interesujących nas zdarzeń. Pomogą nam w tym statyczne metody klasy WaitHandle: SignalAndWait(), WaitAll(), WaitAny(). Przykładowo poniższy kod oczekuje na któryś z dwóch sygnałów i dla każdego z nich wykonuje inną operację:

int ev = EventWaitHandle.WaitAny(new WaitHandle[] {signalA, signalB});

switch (ev)
{
    case 0:
        Console.WriteLine("Signal A ...");
        break;
    case 1:
        Console.WriteLine("Signal B ...");
        break;
}

Zwykle kod nasłuchujący warto jest umieścić w osobnym wątku aby nie blokować głównej pętli programu.

Przykład

Przykład składa się z dwóch prostych aplikacji konsolowych z których jedna tworzy zdarzenia (EventCreator) a druga ich nasłuchuje (EventSubscriber). Uruchamiając należy pamiętać o kolejności.

Named Events Sample

Implementacja w .NET CF

W najnowszej wersji .NET Compact Framework 3.5 pojawiła się implementacja klasy EventWaitHandle niestety pozostawia ona sporo do życzenia. Przede wszystkim nie umożliwia nadawania nazwy naszym zdarzeniom co ogranicza nas do komunikacji w ramach jednej aplikacji. Nie udało mi się również zmusić jej do współpracy z metodami natywnymi (P/Invoke). Nic jednak straconego, w książce ‚Mobile Development Handbook‚ autorzy zamieścili własną implementację, pracującą poprawnie jak i zawierającą kilka dodatkowych metod dostępnych w pełnej wersji .NET Framework’s. Kod źródłowy przykładów załączonych do książki można znaleźć tutaj.

Written by sakowicz

Czerwiec 27, 2008 @ 3:28 pm

Napisane w Misc

Odpowiedzi: 2

Subscribe to comments with RSS.

  1. Z tego co wiem, to nie da sie tego uzyc do komunikacji pomiedzy procesami. Co najwyzej w ramach tego samego procesu.

    Pawel Pabich

    Czerwiec 30, 2008 at 12:50 pm

  2. Jeśli korzystasz z .NET 2.0 wzwyż – jest to jak najbardziej możliwe.

    sakowicz

    Czerwiec 30, 2008 at 1:43 pm


Skomentuj

Wprowadź swoje dane lub kliknij jedną z tych ikon, aby się zalogować:

Logo WordPress.com

Komentujesz korzystając z konta WordPress.com. Log Out / Zmień )

Zdjęcie z Twittera

Komentujesz korzystając z konta Twitter. Log Out / Zmień )

Facebook photo

Komentujesz korzystając z konta Facebook. Log Out / Zmień )

Google+ photo

Komentujesz korzystając z konta Google+. Log Out / Zmień )

Connecting to %s

%d bloggers like this: