2016-06-09 27 views
5

Mam znaczący sposób na opracowanie rozbudowanej aplikacji WPF, która będzie sterować zaawansowanym sprzętem za pośrednictwem komunikatorów szeregowych. Na samym dole aplikacji "stos" mam seryjny poziom komunikacyjny (wykorzystujący klasę .Net "SerialPort"). Czytanie i pisanie do urządzenia h/w jest podstawową częścią systemu, wykorzystywaną przez wiele różnych obszarów warstwy logiki biznesowej, często przeplatanych złożonymi obliczeniami naukowymi i inną taką logiką; te metody BLL są z kolei wywoływane z całego poziomu warstwy interfejsu użytkownika.Czy powinienem używać asynchronicznego "do końca" dla mojej aplikacji GUI?

Obecnie wszystko w warstwie logiki biznesowej, w tym odczyt i zapis SerialPort, jest synchroniczne. Jedyny przypadek, w którym używam async/await, znajduje się w warstwie interfejsu użytkownika, zazwyczaj podczas wywoływania logiki biznesowej. Tutaj będę owijać połączenia w Task.Run(), e.g.:-

private async void SomeButtonClick(object sender, EventArgs e) 
{ 
    await Task.Run(() => _someBLLService.TurnPumpOn()); 
} 

Jest to prosty przykład, który zajmuje się kwestią milisekund. Bardziej złożonym przykładem byłoby rozpoczęcie długotrwałego procesu (ponownie przy użyciu powyższej techniki); ta "usługa" logiki biznesowej będzie działać przez kilka sekund lub minut, zbierając dane ze sprzętu i wykonując inne funkcje "kontrolne" w tym czasie. Okresowo będzie transmitować dane z powrotem do interfejsu użytkownika w celu wykreślania na wykresie (za pośrednictwem struktury agregatora zdarzeń pubsub). Powyższa technika działa dobrze, dzięki czemu interfejs użytkownika pozostaje responsywny, podczas gdy takie procesy warstwy biznesowej mają miejsce.

Niedawno rozważałem przejście "asynchronizacji do końca", zaczynając od kodu komunikacji szeregowej (na przykład za pomocą .ReadAsync), ale miałoby to reperkusje w całym systemie. Dziesiątki (jeśli nie setki) metod logiki biznesowej powinny być refaktoryzowane w metody asynchroniczne, aż do warstwy interfejsu użytkownika. Tu będę w stanie uprościć nieco powyższy kod:

private async void SomeButtonClick(object sender, EventArgs e) 
{ 
    await _someBLLService.TurnPumpOn(); 
} 

Choć nie jestem przeciwny walce dużych zadań refaktoryzacji, zastanawiam się, jakie korzyści są naprawdę. Wielu ludzi (np. Stephen Cleary) popiera rozwiązanie "asynchroniczne", ale głównym celem wydaje się być utrzymywanie czułości interfejsu użytkownika podczas wywoływania długotrwałego procesu BLL, który już wykonuje moja technika Task.Run().

+2

Wyjaśnienie, "asynchronizacja do końca" to inny sposób powiedzenia "nie blokuj kodu asynchronicznego" - działa tylko w jedną stronę.W przypadku aplikacji UI podstawową zaletą async jest responsywność, a 'await Task.Run' to doskonałe rozwiązanie, jeśli ci to działa. –

Odpowiedz

7

Ponieważ Twoja aplikacja (prawdopodobnie) nie jest pod dużym obciążeniem i jest aplikacją GUI, jedynym powodem używania asynchronicznego i oczekiwanego jest wzrost wydajności. Przepustowość i skalowalność nie wchodzą w obraz.

Dlatego rób to, co jest dla ciebie najbardziej wygodne. Może to równie dobrze być wzór await Task.Run, który został użyty w przykładowym kodzie.

ale będzie to miało reperkusje w całym systemie

Tak. Async ma zauważalny koszt produktywności i jest zaraźliwy. Rób to tylko wtedy, gdy wyraźnie możesz wyrazić korzyści, które czerpiesz z tego wyboru. Jedyną korzyścią jest to, że twój kod UI jest krótszy o kilka znaków. Jest to różnica między Twoimi dwoma fragmentami kodu. Cała reszta systemu pogarsza się.

Być może śledziliście społeczność C# i wybrali trend do asynchronizacji. Programiści są bardzo skłonni do przeskakiwania do magicznych rozwiązań bez ich zrozumienia. Wielu zwolenników asynchronizmu nie może nawet wyrazić konkretnych korzyści, jakie z tego płyną. Istnieje również wiele grup myślących. Nie opieraj swojej decyzji wyłącznie na doradztwie internetowym. Czynnik, który wchodzi i sprawdź sam, co ma sens.

+0

To tylko aplikacja na komputery stacjonarne, ale istnieją plany użycia SignalR do ujawnienia pewnych metod BLL, np. dla klienta smartfona, który zapewnia ograniczoną kontrolę nad urządzeniem h/w (nie więcej niż jednym lub dwoma klientami). Rozumiem, że SignalR obsługuje asynchroniczne połączenia z klientami, więc prawdopodobnie nadal nie jest wystarczająco dobrym powodem do asynchronizacji w całym tekście? –

+0

SignalR umożliwia zwrot zadania do niego. Zadanie to może być po prostu 'Task.FromResult' lub w inny sposób, aby utworzyć zadanie" manekina ". Jeśli nie ma obciążenia, nie ma problemów z perfekcją. SignalR * wewnętrznie * użyje wydajnego gniazda IO i odniosę z tego korzyści. – usr