Udostępnij za pośrednictwem


Podsumowanie rozdziału 20. Asynchroniczne operacje we/wy i operacje we/wy plików

Uwaga

Ta książka została opublikowana wiosną 2016 roku i od tego czasu nie została zaktualizowana. Jest wiele w książce, która pozostaje cenna, ale niektóre materiały są nieaktualne, a niektóre tematy nie są już całkowicie poprawne ani kompletne.

Graficzny interfejs użytkownika musi reagować sekwencyjnie na zdarzenia wejściowe użytkownika. Oznacza to, że wszystkie operacje przetwarzania zdarzeń wejściowych użytkownika muszą występować w jednym wątku, często nazywanym wątkiem głównym lub wątkiem interfejsu użytkownika.

Użytkownicy oczekują, że graficzne interfejsy użytkownika będą reagować. Oznacza to, że program musi szybko przetwarzać zdarzenia wejściowe użytkownika. Jeśli to nie jest możliwe, przetwarzanie musi zostać zdegradowane do pomocniczych wątków wykonywania.

W tej książce użyto WebRequest kilku przykładowych programów. W tej klasie BeginGetResponse metoda uruchamia wątek procesu roboczego, który wywołuje funkcję wywołania zwrotnego po zakończeniu. Jednak ta funkcja wywołania zwrotnego jest uruchamiana w wątku procesu roboczego, więc program musi wywołać Device.BeginInvokeOnMainThread metodę w celu uzyskania dostępu do interfejsu użytkownika.

Uwaga

Xamarin.Forms programy powinny być używane HttpClient , a nie WebRequest do uzyskiwania dostępu do plików przez Internet. HttpClient obsługuje operacje asynchroniczne.

Bardziej nowoczesne podejście do przetwarzania asynchronicznego jest dostępne na platformie .NET i w języku C#. Obejmuje Task to klasy i Task<TResult> oraz inne typy w System.Threading przestrzeniach nazw iSystem.Threading.Tasks, a także słowa kluczowe języka C# 5.0async.await To właśnie ten rozdział koncentruje się na.

Od wywołań zwrotnych do oczekiwania

Sama Page klasa zawiera trzy metody asynchroniczne do wyświetlania pól alertów:

Obiekty Task wskazują, że te metody implementują asynchroniczny wzorzec oparty na zadaniach, znany jako TAP. Te Task obiekty są szybko zwracane z metody . Wartości Task<T> zwracane stanowią "obietnicę", że wartość typu TResult będzie dostępna po zakończeniu zadania. Wartość Task zwracana wskazuje akcję asynchroniczną, która zostanie ukończona, ale bez zwracanej wartości.

We wszystkich tych przypadkach element Task zostanie ukończony, gdy użytkownik odrzuci pole alertu.

Alert z wywołaniami zwrotnymi

W przykładzie AlertCallbacks pokazano, jak obsługiwać Task<bool> obiekty zwracane i Device.BeginInvokeOnMainThread wywołania przy użyciu metod wywołania zwrotnego.

Alert z lambdami

W przykładzie AlertLambdas pokazano, jak używać anonimowych funkcji lambda do obsługi wywołań i Device.BeginInvokeOnMainThread ich obsługiTask.

Alert z oczekiwaniem

Bardziej proste podejście obejmuje async słowa kluczowe i await wprowadzone w języku C# 5. Przykład AlertAwait demonstruje ich użycie.

Alert z niczym

Jeśli metoda asynchroniczna zwraca Task wartość zamiast Task<TResult>, program nie musi używać żadnej z tych technik, jeśli nie musi wiedzieć, kiedy zadanie asynchroniczne zostanie zakończone. Przykład NothingAlert pokazuje to.

Asynchroniczne zapisywanie ustawień programu

W przykładzie SaveProgramChanges pokazano użycie SavePropertiesAsync metody Application zapisywania ustawień programu w miarę ich zmiany bez zastępowania OnSleep metody .

Czasomierz niezależny od platformy

Istnieje możliwość utworzenia Task.Delay czasomierza niezależnego od platformy. Przykład TaskDelayClock pokazuje to.

Dane wejściowe/wyjściowe pliku

Tradycyjnie przestrzeń nazw platformy .NET System.IO była źródłem obsługi we/wy plików. Chociaż niektóre metody w tej przestrzeni nazw obsługują operacje asynchroniczne, większość z nich nie obsługuje. Przestrzeń nazw obsługuje również kilka prostych wywołań metod, które wykonują zaawansowane funkcje we/wy plików.

Dobra wiadomość i złe wieści

Wszystkie platformy obsługiwane przez Xamarin.Forms obsługę magazynu lokalnego aplikacji — magazyn prywatny dla aplikacji.

Biblioteki platform Xamarin.iOS i Xamarin.Android zawierają wersję platformy .NET, którą platforma Xamarin została wyraźnie dopasowana do tych dwóch platform. Należą do nich klasy System.IO , których można użyć do wykonywania operacji we/wy plików z magazynem lokalnym aplikacji na tych dwóch platformach.

Jeśli jednak wyszukasz te System.IO klasy w Xamarin.Forms PCL, nie znajdziesz ich. Problem polega na tym, że firma Microsoft całkowicie przebudował we/wy pliku dla interfejsu API środowisko wykonawcze systemu Windows. Programy przeznaczone dla systemu Windows 8.1, Windows Phone 8.1 i platforma uniwersalna systemu Windows nie są używane System.IO do we/wy pliku.

Oznacza to, że należy użyć elementu DependencyService (po raz pierwszy omówionego w rozdziale 9). Wywołania interfejsu API specyficzne dla platformy do implementowania operacji we/wy plików.

Uwaga

Przenośne biblioteki klas zostały zastąpione bibliotekami .NET Standard 2.0, a platforma .NET Standard 2.0 obsługuje System.IO typy dla wszystkich Xamarin.Forms platform. Nie jest już konieczne używanie elementu DependencyService dla większości zadań we/wy plików. Aby uzyskać bardziej nowoczesne podejście do operacji we/wy plików, zobacz Obsługa plików w programie Xamarin.Forms .

Pierwszy strzał w wieloplatformowym pliku we/wy

Przykład TextFileTryout definiuje IFileHelper interfejs dla we/wy plików i implementacje tego interfejsu na wszystkich platformach. Jednak implementacje środowisko wykonawcze systemu Windows nie działają z metodami w tym interfejsie, ponieważ metody we/wy pliku środowisko wykonawcze systemu Windows są asynchroniczne.

Alokowanie operacji we/wy pliku środowisko wykonawcze systemu Windows

Programy działające w ramach środowisko wykonawcze systemu Windows używają klas w przestrzeniach nazw i Windows.Storage.Streams dla we/wy plików, w Windows.Storage tym magazynu lokalnego aplikacji. Ponieważ firma Microsoft ustaliła, że każda operacja wymagająca więcej niż 50 milisekund powinna być asynchroniczna, aby uniknąć blokowania wątku interfejsu użytkownika, te metody we/wy plików są głównie asynchroniczne.

Kod demonstrujący to nowe podejście będzie znajdować się w bibliotece, dzięki czemu może być używany przez inne aplikacje.

Biblioteki specyficzne dla platformy

Korzystne jest przechowywanie kodu wielokrotnego użytku w bibliotekach. Jest to oczywiście trudniejsze, gdy różne fragmenty kodu wielokrotnego użytku są przeznaczone dla zupełnie różnych systemów operacyjnych.

Rozwiązanie Xamarin.FormsBook.Platform demonstruje jedno podejście. To rozwiązanie zawiera siedem różnych projektów:

Wszystkie poszczególne projekty platform (z wyjątkiem Xamarin.FormsBook.Platform.WinRT) mają odwołania do Xamarin.FormsBook.Platform. Trzy projekty systemu Windows zawierają odwołanie do Xamarin.FormsBook.Platform.WinRT.

Wszystkie projekty zawierają metodę statyczną Toolkit.Init , aby upewnić się, że biblioteka jest ładowana, jeśli nie jest bezpośrednio przywoływany przez projekt w rozwiązaniu Xamarin.Forms aplikacji.

Projekt Xamarin.FormsBook.Platform zawiera nowy IFileHelper interfejs. Wszystkie metody mają teraz nazwy z Async sufiksami i zwracanymi Task obiektami.

Projekt Xamarin.FormsBook.Platform.WinRT zawiera klasę FileHelper środowisko wykonawcze systemu Windows.

Projekt Xamarin.FormsBook.Platform.iOS zawiera klasę FileHelper dla systemu iOS. Te metody muszą być teraz asynchroniczne. Niektóre metody używają asynchronicznych wersji metod zdefiniowanych w systemach StreamWriter i : StreamReaderWriteAsync i ReadToEndAsync. Inni konwertują Task wynik na obiekt przy użyciu FromResult metody .

Projekt Xamarin.FormsBook.Platform.Android zawiera podobną FileHelper klasę dla systemu Android.

Projekt Xamarin.FormsBook.Platform zawiera również klasę FileHelper , która ułatwia korzystanie z DependencyService obiektu.

Aby korzystać z tych bibliotek, rozwiązanie aplikacji musi zawierać wszystkie projekty w rozwiązaniu Xamarin.FormsBook.Platform , a każdy z projektów aplikacji musi mieć odwołanie do odpowiedniej biblioteki w Xamarin.Formsbook.platform.

Rozwiązanie TextFileAsync pokazuje, jak używać Xamarin.Formsbibliotek Book.Platform . Każdy z projektów ma wywołanie metody Toolkit.Init. Aplikacja korzysta z asynchronicznych funkcji we/wy pliku.

Utrzymywanie go w tle

Metody w bibliotekach, które tworzą wywołania wielu metod asynchronicznych — takich jak WriteFileAsync metody i ReadFileASync w klasie środowisko wykonawcze systemu Windows FileHelper — mogą być nieco bardziej wydajne przy użyciu ConfigureAwait metody , aby uniknąć powrotu do wątku interfejsu użytkownika.

Nie blokuj wątku interfejsu użytkownika!

Czasami kuszące jest unikanie użycia właściwości ContinueWith lub await przy użyciu Result właściwości w metodach. Należy tego uniknąć, ponieważ może zablokować wątek interfejsu użytkownika, a nawet zawiesić aplikację.

Własne metody oczekujące

Możesz uruchomić kod asynchronicznie, przekazując go do jednej z Task.Run metod. Możesz wywołać Task.Run metodę asynchroniową, która obsługuje niektóre obciążenia.

Różne Task.Run wzorce zostały omówione poniżej.

Podstawowy zestaw Mandelbrot

Aby narysować mandelbrot ustawiony w czasie rzeczywistym, Xamarin.Forms. Biblioteka zestawu narzędzi ma strukturę podobną Complex do tej w System.Numerics przestrzeni nazw.

Przykład MandelbrotSet zawiera metodę CalculateMandeblotAsync w pliku za kodem, która oblicza podstawowy zestaw mandelbrot i używa BmpMaker go do umieszczania go na mapie bitowej.

Znakowanie postępu

Aby zgłosić postęp z metody asynchronicznej, możesz utworzyć wystąpienie klasy i zdefiniować metodę Progress<T> asynchroniczną, aby mieć argument typu IProgress<T>. Jest to pokazane w przykładzie MandelbrotProgress .

Anulowanie zadania

Możesz również napisać metodę asynchroniczną, aby można było anulować. Zaczynasz od klasy o nazwie CancellationTokenSource. Właściwość Token jest wartością typu CancellationToken. Jest on przekazywany do funkcji asynchronicznej. Program wywołuje metodę Cancel CancellationTokenSource (zazwyczaj w odpowiedzi na akcję przez użytkownika), aby anulować funkcję asynchroniczną.

Metoda asynchroniczna może okresowo sprawdzać IsCancellationRequested właściwość i wyjść, jeśli właściwość ma truewartość CancellationToken , lub po prostu wywołaj ThrowIfCancellationRequested metodę , w tym przypadku metoda kończy się ciągiem OperationCancelledException.

Przykład MandelbrotCancellation demonstruje użycie funkcji z możliwością anulowania.

An MVVM Mandelbrot

Przykład MandelbrotXF ma bardziej rozbudowany interfejs użytkownika i opiera się głównie na MandelbrotModel klasach i MandelbrotViewModel :

Potrójny zrzut ekranu narzędzia Mandelbrot X F

Powrót do sieci Web

Klasa WebRequest używana w niektórych przykładach używa staroświetnego protokołu asynchronicznego nazywanego asynchronicznym modelem programowania lub APM. Taką klasę można przekonwertować na nowoczesny protokół TAP przy użyciu jednej z FromAsync metod w TaskFactory klasie . Przykład ApmToTap pokazuje to.