2011-08-18 12 views
11

Niedawno natknąłem się na klasę AsyncEnumerator z biblioteki Power Threading Library Jeffreya Richtera, która wydaje się rozwiązywać kilka problemów, które zwykle napotykam podczas programowania rzeczy asynchronicznych.Czy nadal potrzebujemy AsyncEnumeratora Richtera?

Pomysł na tę klasę istnieje już od jakiegoś czasu i zastanawiam się, czy obecne wersje .NET/C# mają wbudowaną obsługę tego mechanizmu, czy też nadal konieczne jest poleganie na trzecia biblioteka? A może nowsze wersje .NET mają alternatywne podejście, które upraszcza programowanie asynchroniczne tak, jak robi to AsyncEnumerator Richtera?

Innymi słowy: czy istnieje powód, aby nie zacząć korzystać z AsyncEnumeratora Richtera dzisiaj?

Edit:

Niektóre linki z informacjami o AsyncEnumerator:

Odpowiedz

16

Tak, nadal będziesz korzystać z mojego AsyncEnumerator. Nowe wątki wprowadzane w .NET 4 (Zadania, Równoległe, PLINQ, itp.) Dotyczą tylko współbieżności. Oznacza to, że chodzi o pobranie obciążenia obliczeniowego, podzielenie go i utworzenie go na wiele wątków, aby obciążenie mogło zostać wykonane w krótszym czasie, niż wykonanie jednego wątku w celu wykonania całego zadania. Możesz użyć tych konstrukcji do jednoczesnego wykonywania wielu synchronicznych operacji we/wy. Jednak synchroniczne operacje we/wy powodują blokowanie wszystkich wątków, co powoduje, że wątek tworzy więcej wątków. Zużycie zasobów w aplikacji wzrasta, a zużycie procesora pozostaje bardzo niskie. Jest to bardzo nieefektywne w implementowaniu aplikacji i zapobiega skalowaniu aplikacji.

Moje narzędzie AsyncEnumerator polega na inicjowaniu asynchronicznych operacji we/wy bez blokowania żadnych wątków, dzięki czemu zużycie zasobów aplikacji jest bardzo niskie, aby aplikacja działała bardzo dobrze. W tym przypadku użycie procesora pozostaje niskie, ponieważ wykonujesz operacje wejścia/wyjścia; nie obciążenie pracą obliczeniową.

W następnej wersji .NET nowe funkcje języka async/await (z którymi współpracowałem z Microsoftem) umożliwiają wykonywanie asynchronicznych operacji wejścia/wyjścia, a nowe funkcje są bardzo podobne do mojego AsyncEnumeratora . Tak bardzo, że możesz kod portu, który używa mojego AsyncEnumerator do nowego modelu z bardzo niewielu zmianami kodu źródłowego.

Jak ktoś inny wskazał, mój AsyncEnumerator nadal oferuje inne funkcje i działa z .NET 2.0 i nowszymi. Tak więc wiele osób nadal będzie to przydatne przez długi czas.

+0

Dziękuję za wyjaśnienia! Zacząłem korzystać z twojej biblioteki i jestem z niej całkiem zadowolony. Nie jestem jednak pewien, jak poprawnie zaimplementować obsługę wyjątków. Może mógłbyś rzucić okiem na moje inne pytanie [tutaj] (http: // stackoverflow.com/questions/7122164/exception-handling-when-implementation-the-apm-pattern-with-asyncenumerator). Wielkie dzięki! –

9

Oczywistym jest PLINQ równolegle tutaj, ale sam Richter dismisses this:

Jeffrey Richter gru 04, 2008 at 2:27 PMquotereply Są bardzo inaczej. Równolegle. W szczególności chodzi o wykonywanie szeregu operacji związanych z obliczeniami równoległymi na wszystkich procesorach w maszynie. Mój AsyncEnumerator polega głównie na wydaniu jednego lub więcej współbieżnych operacji wejścia/wyjścia bez żadnych bloków wątków, aby można je było ukończyć dla .

Jednak C# async CTP mogą być użyteczne tutaj, co kontynuacje wątku znacznie bardziej uzasadnione, tj

var bytesRead = await stream.ReadAsync(...); 
Console.WriteLine(bytesRead); // woah! we're on a different thread now! 

Tutaj kompilator C# re-pisze wszystko wokół await instuctions, tak że staje się ona callback/kontynuacja do istniejącej operacji asynchronicznej (która musi zwracać "wartość oczekiwaną"). Kiedy już to zrobię, mam nadzieję, że stanie się to o wiele bardziej naturalnym sposobem pisania kodu z wewnętrznymi opóźnieniami z powodu asynchronizacji.

+0

Z tego, co widziałem o PLINQ, również nie uważam tego za oczywistą paralelę. To, co podoba mi się w AsyncEnumeratorze, to możliwość wyrażania sekwencji asynchronicznych operacji w bardzo naturalny sposób (np. Łączenie się z serwerem sieciowym, żądanie pewnych danych, na podstawie żądania wyników innych danych). Wszystko to wygląda jak program synchroniczny. Oprócz tego masz wsparcie dla anulowania/limitu czasu i nie musisz się martwić o zestawianie do wątku interfejsu użytkownika. Nie widzę, jak poradziłbym sobie z czymś takim z PLINQ. –

+0

@Robert, który jest *** dokładnie ***, co 'await' ma, też - w regularnym wyglądzie C#. 'var response = czekaj na GetResponse();' etc –

+0

Co do oczekiwanego słowa kluczowego ... Chciałbym trzymać się tego, co jest obecnie dostępne (piszę kod produkcyjny) –

0

Z tym pytaniem Asynchronous iterator Task<IEnumerable<T>>:

Brzmi jak czego można naprawdę szukasz jest coś IObservable<T>, czyli coś w rodzaju push-oparty asynchronicznego IEnumerable <T>. Zobacz Reactive Extensions, a.k.a. Rx z Microsoft Open Technologies (kod na licencji Apache-2.0) (brak powiązań) dla ogromnej liczby metod, które działają z IObservable <T>, aby działało jak LINQ-to-Objects i wiele innych.

Problem z IEnumerable <T> polega na tym, że nic tak naprawdę nie powoduje, że wyliczenie jest asynchroniczne. Jeśli nie chcesz, aby dodać zależność od Rx (co jest naprawdę co sprawia IObservable <T> Shine), to alternatywą może pracować dla Ciebie:

public async Task<IEnumerable<char>> TestAsync(string testString) 
{ 
    return GetChars(testString); 
} 

private static IEnumerable<char> GetChars(string testString) 
{ 
    foreach (char c in testString.ToCharArray()) 
    { 
     // do other work 
     yield return c; 
    } 
} 

chociaż chciałbym podkreślić poza tym, że nie wiedząc, co ** faktycznie robi się asynchronicznie, może być o wiele lepszy sposób na osiągnięcie swoich celów. Żaden z opublikowanych przez ciebie kodów nie będzie robił nic asynchronicznie, i nie wiem, czy coś w // do other work jest asynchroniczne (w takim przypadku nie jest to rozwiązanie problemu, chociaż spowoduje to kompilację twojego kodu).

Powiązane problemy