Shrnutí kapitoly 20. Asynchronní a souborové I/O
Poznámka:
Tato kniha byla publikována na jaře roku 2016 a od té doby nebyla aktualizována. Existuje mnoho v knize, která zůstává cenná, ale některé materiály jsou zastaralé a některá témata už nejsou zcela správná nebo úplná.
Grafické uživatelské rozhraní musí reagovat na události vstupu uživatele postupně. To znamená, že veškeré zpracování událostí uživatelského vstupu musí nastat v jednom vlákně, často označované jako hlavní vlákno nebo vlákno uživatelského rozhraní.
Uživatelé očekávají, že grafická uživatelská rozhraní budou responzivní. To znamená, že program musí rychle zpracovávat události uživatelského vstupu. Pokud to není možné, musí být zpracování přelegováno na sekundární vlákna provádění.
V této knize bylo použito WebRequest
několik ukázkových programů. V této třídě BeginGetResponse
metoda spustí pracovní vlákno, které volá funkci zpětného volání po dokončení. Tato funkce zpětného volání však běží v pracovním vlákně, takže program musí volat Device.BeginInvokeOnMainThread
metodu pro přístup k uživatelskému rozhraní.
Poznámka:
Xamarin.Forms programy by neměly používat HttpClient
místo WebRequest
přístupu k souborům přes internet. HttpClient
podporuje asynchronní operace.
Modernější přístup k asynchronnímu zpracování je k dispozici v .NET a C#. To zahrnuje třídy Task
a Task<TResult>
další typy v oborech System.Threading
názvů a System.Threading.Tasks
také jazyk C# 5.0 async
a await
klíčová slova. To je to, na co se tato kapitola zaměřuje.
Od zpětného volání do operátoru await
Samotná Page
třída obsahuje tři asynchronní metody pro zobrazení polí výstrah:
DisplayAlert
vrátí objekt.Task
DisplayAlert
vrátí objekt.Task<bool>
DisplayActionSheet
vrátí objekt.Task<string>
Objekty Task
označují, že tyto metody implementují asynchronní vzor založený na úlohách, označovaný jako TAP. Tyto Task
objekty jsou rychle vráceny z metody. Návratové Task<T>
hodnoty představují "příslib", že hodnota typu TResult
bude k dispozici po dokončení úkolu. Vrácená Task
hodnota označuje asynchronní akci, která se dokončí, ale bez vrácené hodnoty.
Ve všech těchtopřípadechch Task
Upozornění se zpětnými voláními
Ukázka AlertCallbacks ukazuje, jak zpracovat Task<bool>
návratové objekty a Device.BeginInvokeOnMainThread
volání pomocí metod zpětného volání.
Upozornění s lambdami
Ukázka AlertLambdas ukazuje, jak používat anonymní funkce lambda pro zpracování Task
a Device.BeginInvokeOnMainThread
volání.
Výstraha s operátorem Await
Jednodušší přístup zahrnuje async
await
klíčová slova představená v jazyce C# 5. Ukázka AlertAwait ukazuje jejich použití.
Upozornění s nic
Pokud asynchronní metoda vrátí Task
místo Task<TResult>
, pak program nemusí používat žádné z těchto technik, pokud nepotřebuje vědět, kdy asynchronní úkol dokončí. Ukázka NothingAlert ukazuje tuto akci.
Asynchronní ukládání nastavení programu
Ukázka SaveProgramChanges ukazuje použití SavePropertiesAsync
metody Application
uložení nastavení programu při jejich změně bez přepsání OnSleep
metody.
Časovač nezávislý na platformě
Je možné použít Task.Delay
k vytvoření časovače nezávislého na platformě. Ukázka TaskDelayClock ukazuje tuto možnost.
Vstup/výstup souboru
Tradičně byl obor názvů .NET System.IO
zdrojem podpory vstupně-výstupních operací souborů. I když některé metody v tomto oboru názvů podporují asynchronní operace, většina ne. Obor názvů také podporuje několik jednoduchých volání metod, která provádějí sofistikované vstupně-výstupní funkce souborů.
Dobré zprávy a špatné zprávy
Všechny platformy podporované Xamarin.Forms podporou místního úložiště aplikace – úložiště, které je pro aplikaci soukromé.
Knihovny Xamarin.iOS a Xamarin.Android zahrnují verzi rozhraní .NET, kterou Xamarin výslovně přizpůsobila těmto dvěma platformám. Patří sem třídy, které System.IO
můžete použít k provádění vstupně-výstupních operací se soubory s místním úložištěm aplikace na těchto dvou platformách.
Pokud ale tyto System.IO
třídy vyhledáte v Xamarin.Forms PCL, nenajdete je. Problémem je, že Microsoft zcela přepracoval vstupně-výstupní operace souboru pro rozhraní API prostředí Windows Runtime. Programy cílené na Windows 8.1, Windows Phone 8.1 a Univerzální platforma Windows nepoužívají System.IO
pro vstupně-výstupní operace souborů.
To znamená, že budete muset použít DependencyService
(první probíranou v kapitole 9). Volání rozhraní API specifická pro platformu pro implementaci vstupně-výstupních operací souborů
Poznámka:
Knihovny přenosných tříd byly nahrazeny knihovnami .NET Standard 2.0 a .NET Standard 2.0 podporuje System.IO
typy pro všechny Xamarin.Forms platformy. Pro většinu vstupně-výstupních úloh souborů už není nutné používat DependencyService
. Další moderní přístup k vstupně-výstupním operacím souborů najdete v Xamarin.Forms tématu Zpracování souborů.
První snímek při vstupně-výstupních operacích souborů napříč platformami
Ukázka TextFileTryout definuje IFileHelper
rozhraní pro vstupně-výstupní operace souboru a implementace tohoto rozhraní na všech platformách. Implementace prostředí Windows Runtime ale s metodami v tomto rozhraní nefungují, protože prostředí Windows Runtime vstupně-výstupní metody souboru jsou asynchronní.
Přizpůsobení vstupně-výstupních operací prostředí Windows Runtime souboru
Programy spuštěné v rámci prostředí Windows Runtime používají třídy v Windows.Storage
oborech Windows.Storage.Streams
názvů pro vstupně-výstupní operace souborů, včetně místního úložiště aplikace. Vzhledem k tomu, že Společnost Microsoft zjistila, že jakákoli operace vyžadující více než 50 milisekund by měla být asynchronní, aby nedošlo k blokování vlákna uživatelského rozhraní, jsou tyto vstupně-výstupní metody souborů většinou asynchronní.
Kód demonstrující tento nový přístup bude v knihovně, aby ho mohly používat jiné aplikace.
Knihovny specifické pro platformu
Je výhodné uložit opakovaně použitelný kód v knihovnách. To je samozřejmě obtížnější, když různé části opakovaně použitelného kódu jsou pro zcela různé operační systémy.
Řešení Xamarin.FormsBook.Platform ukazuje jeden přístup. Toto řešení obsahuje sedm různých projektů:
- Xamarin.FormsBook.Platform, normální Xamarin.Forms PCL
- Xamarin.FormsBook.Platform.iOS, knihovna tříd pro iOS
- Xamarin.FormsBook.Platform.Android, knihovna tříd pro Android
- Xamarin.FormsBook.Platform.UWP, univerzální knihovna tříd Windows
- Xamarin.FormsBook.Platform.WinRT– sdílený projekt pro kód, který je společný pro všechny platformy Windows
Všechny projekty jednotlivých platforem (s výjimkou Book.Platform.WinRT) mají odkazy na Xamarin.FormsBook.Platform.Xamarin.Forms Tři projekty Windows mají odkaz na Xamarin.FormsBook.Platform.WinRT.
Všechny projekty obsahují statickou Toolkit.Init
metodu, která zajistí, že se knihovna načte, pokud na ni projekt v Xamarin.Forms řešení aplikace přímo neodkazuje.
Projekt Xamarin.FormsBook.Platform obsahuje nové IFileHelper
rozhraní. Všechny metody teď mají názvy s příponami Async
a návratové Task
objekty.
Projekt Xamarin.FormsBook.Platform.WinRT obsahuje FileHelper
třídu pro prostředí Windows Runtime.
Projekt Xamarin.FormsBook.Platform.iOS obsahuje FileHelper
třídu pro iOS. Tyto metody teď musí být asynchronní. Některé metody používají asynchronní verze metod definovaných v StreamWriter
: StreamReader
WriteAsync
a ReadToEndAsync
. Ostatní převedou výsledek na Task
objekt pomocí FromResult
metody.
Projekt Xamarin.FormsBook.Platform.Android obsahuje podobnou FileHelper
třídu pro Android.
Projekt Xamarin.FormsBook.Platform obsahuje FileHelper
také třídu, která usnadňuje použití objektu DependencyService
.
Aby bylo možné tyto knihovny používat, musí řešení aplikace obsahovat všechny projekty v Xamarin.Formsřešení Book.Platform a každý z projektů aplikace musí mít odkaz na odpovídající knihovnu v Xamarin.FormsBook.Platform.
Řešení TextFileAsync ukazuje, jak používat Xamarin.Formsknihovny Book.Platform . Každý z projektů má volání Toolkit.Init
. Aplikace využívá asynchronní vstupně-výstupní funkce souborů.
Zachování na pozadí
Metody v knihovnách, které provádějí volání více asynchronních metod , jako WriteFileAsync
ReadFileASync
jsou metody ve třídě prostředí Windows Runtime FileHelper
, mohou být poněkud efektivnější pomocí ConfigureAwait
metody, aby se zabránilo přepnutí zpět do vlákna uživatelského rozhraní.
Nezablokujte vlákno uživatelského rozhraní!
Někdy je lákavé vyhnout se použití ContinueWith
nebo await
použití Result
vlastnosti v metodách. Tomu by se mělo vyhnout, protože může blokovat vlákno uživatelského rozhraní nebo dokonce zablokovat aplikaci.
Vaše vlastní očekávané metody
Určitý kód můžete spustit asynchronně tak, že ho předáte jedné z Task.Run
metod. Můžete volat Task.Run
v asynchronní metodě, která zpracovává některé režijní náklady.
Task.Run
Různé vzory jsou popsány níže.
Základní sada Mandelbrot
Chcete-li nakreslit Mandelbrot v reálném čase, Xamarin.Forms Knihovna toolkit má strukturu podobnou Complex
té v System.Numerics
oboru názvů.
Ukázka MandelbrotSet má v souboru kódu metodu CalculateMandeblotAsync
, která vypočítá základní černobílou sadu Mandelbrot a používá BmpMaker
ji k jeho vložení na rastrový obrázek.
Označení průběhu
Pokud chcete hlásit průběh z asynchronní metody, můžete vytvořit instanci Progress<T>
třídy a definovat asynchronní metodu tak, aby měla argument typu IProgress<T>
. To je ukázáno ve vzorku MandelbrotProgress.
Zrušení úlohy
Můžete také napsat asynchronní metodu, která se dá zrušit. Začínáte třídou s názvem CancellationTokenSource
. Vlastnost Token
je hodnota typu CancellationToken
. Tato funkce se předá asynchronní funkci. Program volá metodu Cancel
CancellationTokenSource
(obecně v reakci na akci uživatelem) pro zrušení asynchronní funkce.
Asynchronní metoda může pravidelně kontrolovat IsCancellationRequested
vlastnost CancellationToken
a ukončit, pokud je true
vlastnost , nebo jednoduše volat metoduThrowIfCancellationRequested
, v takovém případě metoda končí .OperationCancelledException
Ukázka MandelbrotCancellation demonstruje použití zrušené funkce.
An MVVM Mandelbrot
Ukázka MandelbrotXF má rozsáhlejší uživatelské rozhraní a je většinou založená na třídách MandelbrotModel
MandelbrotViewModel
:
Zpět na web
Třída WebRequest
použitá v některých ukázkách používá starý asynchronní protokol s názvem Asynchronní programovací model nebo APM. Takovou třídu můžete převést na moderní protokol TAP pomocí jedné z FromAsync
metod ve TaskFactory
třídě. Ukázka ApmToTap to ukazuje.