Condividi tramite


Riepilogo del capitolo 20. I/O asincrono e su file

Nota

Questo libro è stato pubblicato nella primavera del 2016, e non è stato aggiornato da allora. C'è molto nel libro che rimane prezioso, ma alcuni materiali sono obsoleti, e alcuni argomenti non sono più completamente corretti o completi.

Un'interfaccia utente grafica deve rispondere agli eventi di input dell'utente in sequenza. Ciò implica che tutte le elaborazioni degli eventi di input utente devono verificarsi in un singolo thread, spesso denominato thread principale o thread dell'interfaccia utente.

Gli utenti si aspettano che le interfacce utente grafiche siano reattive. Ciò significa che un programma deve elaborare rapidamente gli eventi di input dell'utente. Se ciò non è possibile, l'elaborazione deve essere retrocessa a thread secondari di esecuzione.

Diversi programmi di esempio in questo libro hanno usato la WebRequest classe . In questa classe il BeginGetResponse metodo avvia un thread di lavoro, che chiama una funzione di callback al termine. Tuttavia, tale funzione di callback viene eseguita nel thread di lavoro, pertanto il programma deve chiamare Device.BeginInvokeOnMainThread il metodo per accedere all'interfaccia utente.

Nota

Xamarin.Forms i programmi devono usare HttpClient anziché WebRequest per accedere ai file tramite Internet. HttpClient supporta operazioni asincrone.

Un approccio più moderno all'elaborazione asincrona è disponibile in .NET e C#. Ciò implica le Task classi e Task<TResult> e altri tipi negli System.Threading spazi dei nomi e System.Threading.Tasks , nonché le parole chiave C# 5.0 async e await . Questo è ciò che questo capitolo è incentrato su.

Dai callback ad await

La Page classe stessa contiene tre metodi asincroni per visualizzare le caselle di avviso:

Gli Task oggetti indicano che questi metodi implementano il modello asincrono basato su attività, noto come TAP. Questi Task oggetti vengono restituiti rapidamente dal metodo . I Task<T> valori restituiti costituiscono una "promessa" che un valore di tipo TResult sarà disponibile al termine dell'attività. Il Task valore restituito indica un'azione asincrona che verrà completata ma senza alcun valore restituito.

In tutti questi casi, l'oggetto Task viene completato quando l'utente ignora la casella di avviso.

Avviso con callback

L'esempio AlertCallbacks illustra come gestire Task<bool> gli oggetti restituiti e Device.BeginInvokeOnMainThread le chiamate usando metodi di callback.

Avviso con espressioni lambda

L'esempio AlertLambdas illustra come usare funzioni lambda anonime per la gestione Task e Device.BeginInvokeOnMainThread le chiamate.

Un avviso con await

Un approccio più semplice prevede le async parole chiave e await introdotte in C# 5. L'esempio AlertAwait illustra l'uso.

Un avviso senza nulla

Se il metodo asincrono restituisce Task anziché Task<TResult>, il programma non deve usare alcuna di queste tecniche se non è necessario sapere quando l'attività asincrona viene completata. L'esempio NothingAlert illustra questa operazione.

Salvataggio asincrono delle impostazioni del programma

L'esempio SaveProgramChanges illustra l'uso del SavePropertiesAsync metodo di per salvare le impostazioni del Application programma quando cambiano senza eseguire l'override del OnSleep metodo .

Timer indipendente dalla piattaforma

È possibile usare Task.Delay per creare un timer indipendente dalla piattaforma. L'esempio TaskDelayClock illustra questa operazione.

Input/output dei file

Tradizionalmente, lo spazio dei nomi .NET System.IO è stato l'origine del supporto di I/O dei file. Anche se alcuni metodi in questo spazio dei nomi supportano operazioni asincrone, la maggior parte non lo è. Lo spazio dei nomi supporta anche diverse chiamate di metodo semplici che eseguono funzioni di I/O di file sofisticate.

Buone notizie e cattive notizie

Tutte le piattaforme supportate dal Xamarin.Forms supporto dell'archiviazione locale dell'applicazione, ovvero l'archiviazione privata per l'applicazione.

Le librerie Xamarin.iOS e Xamarin.Android includono una versione di .NET espressamente personalizzata per queste due piattaforme. Queste includono classi da System.IO cui è possibile usare per eseguire operazioni di I/O di file con l'archiviazione locale dell'applicazione in queste due piattaforme.

Tuttavia, se si cerca queste System.IO classi in una Xamarin.Forms libreria di classi, non verranno trovate. Il problema è che l'I/O del file completamente rinnovato da Microsoft per l'API di Windows Runtime. Programmi destinati a Windows 8.1, Windows Telefono 8.1 e le piattaforma UWP (Universal Windows Platform) non usano System.IO per l'I/O dei file.

Ciò significa che sarà necessario usare ( DependencyService prima discusso nel capitolo 9. Chiamate API specifiche della piattaforma per implementare l'I/O dei file.

Nota

Librerie di classi portabili sono state sostituite con librerie .NET Standard 2.0 e .NET Standard 2.0 supporta System.IO tipi per tutte le Xamarin.Forms piattaforme. Non è più necessario usare un DependencyService per la maggior parte delle attività di I/O dei file. Per un approccio più moderno all'I/O dei file, vedere Gestione dei file in Xamarin.Forms .

Un primo colpo all'I/O di file multipiattaforma

L'esempio TextFileTryout definisce un'interfaccia IFileHelper per l'I/O del file e le implementazioni di questa interfaccia in tutte le piattaforme. Tuttavia, le implementazioni di Windows Runtime non funzionano con i metodi in questa interfaccia perché i metodi di I/O del file di Windows Runtime sono asincroni.

Accomodamento delle operazioni di I/O dei file di Windows Runtime

I programmi in esecuzione in Windows Runtime usano classi negli spazi dei nomi e Windows.Storage.Streams per l'IWindows.Storage/O dei file, inclusa l'archiviazione locale dell'applicazione. Poiché Microsoft ha determinato che qualsiasi operazione che richiede più di 50 millisecondi deve essere asincrona per evitare di bloccare il thread dell'interfaccia utente, questi metodi di I/O file sono principalmente asincroni.

Il codice che illustra questo nuovo approccio si troverà in una libreria in modo che possa essere usato da altre applicazioni.

Librerie specifiche della piattaforma

È vantaggioso archiviare il codice riutilizzabile nelle librerie. Questo è ovviamente più difficile quando parti diverse del codice riutilizzabile sono per sistemi operativi completamente diversi.

La Xamarin.Formssoluzione Book.Platform illustra un approccio. Questa soluzione contiene sette progetti diversi:

Tutti i singoli progetti di piattaforma (ad eccezione di Xamarin.FormsBook.Platform.WinRT) hanno riferimenti a Xamarin.FormsBook.Platform. I tre progetti Windows hanno un riferimento a Xamarin.FormsBook.Platform.WinRT.

Tutti i progetti contengono un metodo statico Toolkit.Init per assicurarsi che la libreria venga caricata se non fa riferimento direttamente a un progetto in una Xamarin.Forms soluzione dell'applicazione.

Il Xamarin.Formsprogetto Book.Platform contiene la nuova IFileHelper interfaccia. Tutti i metodi hanno ora nomi con Async suffissi e oggetti restituiti Task .

Il Xamarin.Formsprogetto Book.Platform.WinRT contiene la FileHelper classe per Windows Runtime.

Il Xamarin.Formsprogetto Book.Platform.iOS contiene la FileHelper classe per iOS. Questi metodi devono ora essere asincroni. Alcuni dei metodi usano le versioni asincrone dei metodi definiti in StreamWriter e StreamReader: WriteAsync e ReadToEndAsync. Altri convertono un risultato in un Task oggetto utilizzando il FromResult metodo .

Il Xamarin.Formsprogetto Book.Platform.Android contiene una classe simile FileHelper per Android.

Il Xamarin.Formsprogetto Book.Platform contiene anche una FileHelper classe che semplifica l'uso dell'oggetto DependencyService .

Per usare queste librerie, una soluzione dell'applicazione deve includere tutti i progetti nella soluzione Book.Platform e ognuno dei progetti dell'applicazione deve avere un riferimento alla libreria corrispondente in Xamarin.FormsBook.Platform.Xamarin.Forms

La soluzione TextFileAsync illustra come usare le Xamarin.Formslibrerie Book.Platform. Ogni progetto ha una chiamata a Toolkit.Init. L'applicazione usa le funzioni di I/O di file asincrone.

Mantenerlo in background

I metodi nelle librerie che effettuano chiamate a più metodi asincroni, ad esempio i WriteFileAsync metodi e ReadFileASync nella classe Windows Runtime FileHelper , possono essere resi più efficienti usando il ConfigureAwait metodo per evitare di tornare al thread dell'interfaccia utente.

Non bloccare il thread dell'interfaccia utente.

A volte è consigliabile evitare l'uso di ContinueWith o await usando la Result proprietà sui metodi . Questa operazione deve essere evitata perché può bloccare il thread dell'interfaccia utente o anche bloccare l'applicazione.

Metodi awaitable personalizzati

È possibile eseguire codice in modo asincrono passandolo a uno dei Task.Run metodi . È possibile chiamare Task.Run all'interno di un metodo asincrono che gestisce alcuni sovraccarichi.

Di seguito sono illustrati i vari Task.Run modelli.

Il set di base Di Mandelbrot

Per disegnare il Mandelbrot impostato in tempo reale, il Xamarin.Forms. La libreria toolkit ha una Complex struttura simile a quella nello spazio dei System.Numerics nomi .

L'esempio Di MandelbrotSet ha un CalculateMandeblotAsync metodo nel relativo file code-behind che calcola il set Di base di Mandelbrot nero e bianco e lo BmpMaker usa per inserirlo in una bitmap.

Contrassegno dello stato di avanzamento

Per segnalare lo stato di avanzamento da un metodo asincrono, è possibile creare un'istanza di una Progress<T> classe e definire il metodo asincrono per avere un argomento di tipo IProgress<T>. Questo è dimostrato nell'esempio di MandelbrotProgress .

Annullamento del processo

È anche possibile scrivere un metodo asincrono per essere annullabile. Si inizia con una classe denominata CancellationTokenSource. La Token proprietà è un valore di tipo CancellationToken. Viene passato alla funzione asincrona. Un programma chiama il Cancel metodo di CancellationTokenSource (in genere in risposta a un'azione da parte dell'utente) per annullare la funzione asincrona.

Il metodo asincrono può controllare periodicamente la IsCancellationRequested proprietà di CancellationToken e uscire se la proprietà è trueo semplicemente chiamare il ThrowIfCancellationRequested metodo , nel qual caso il metodo termina con un oggetto OperationCancelledException.

L'esempio Di MandelbrotCancellation illustra l'uso di una funzione annullabile.

Un MVVM Mandelbrot

L'esempio MandelbrotXF ha un'interfaccia utente più estesa ed è basata principalmente su classi MandelbrotModel e MandelbrotViewModel :

Screenshot triplo di Mandelbrot X F

Torna al Web

La WebRequest classe usata in alcuni esempi usa un protocollo asincrono obsoleto denominato modello di programmazione asincrona o APM. È possibile convertire tale classe nel protocollo TAP moderno usando uno dei FromAsync metodi nella TaskFactory classe . L'esempio ApmToTap illustra questa operazione.