Partilhar via


Resumo do Capítulo 20. E/S assíncrona e de arquivo

Observação

Este livro foi publicado na primavera de 2016, e não foi atualizado desde então. Há muito no livro que permanece valioso, mas parte do material está desatualizado, e alguns tópicos não estão mais totalmente corretos ou completos.

Uma interface gráfica do usuário deve responder a eventos de entrada do usuário sequencialmente. Isso implica que todo o processamento de eventos de entrada do usuário deve ocorrer em um único thread, geralmente chamado de thread principal ou thread da interface do usuário.

Os usuários esperam que as interfaces gráficas do usuário sejam responsivas. Isso significa que um programa deve processar eventos de entrada do usuário rapidamente. Se isso não for possível, o processamento deve ser relegado a threads secundários de execução.

Vários programas de exemplo neste livro usaram a WebRequest classe. Nessa classe, o BeginGetResponse método inicia um thread de trabalho, que chama uma função de retorno de chamada quando ela é concluída. No entanto, essa função de retorno de chamada é executada no thread de trabalho, portanto, o programa deve chamar Device.BeginInvokeOnMainThread o método para acessar a interface do usuário.

Observação

Xamarin.Forms Os programas devem ser usados HttpClient em vez de WebRequest acessar arquivos pela Internet. HttpClient Suporta operações assíncronas.

Uma abordagem mais moderna para processamento assíncrono está disponível em .NET e C#. Isso envolve as Task classes e Task<TResult> e outros tipos nos System.Threading namespaces e System.Threading.Tasks , bem como o C# 5.0 async e await palavras-chave. É nisso que este capítulo se concentra.

De retornos de chamada a espera

A Page classe em si contém três métodos assíncronos para exibir caixas de alerta:

Os Task objetos indicam que esses métodos implementam o padrão assíncrono baseado em tarefa, conhecido como TAP. Esses Task objetos são retornados rapidamente do método. Os Task<T> valores de retorno constituem uma "promessa" de que um valor de tipo TResult estará disponível quando a tarefa for concluída. O Task valor de retorno indica uma ação assíncrona que será concluída, mas sem nenhum valor retornado.

Em todos esses casos, o Task é concluído quando o usuário descarta a caixa de alerta.

Um alerta com retornos de chamada

O exemplo AlertCallbacks demonstra como manipular Task<bool> objetos de retorno e Device.BeginInvokeOnMainThread chamadas usando métodos de retorno de chamada.

Um alerta com lambdas

O exemplo AlertLambdas demonstra como usar funções lambda anônimas para manipulação Task e Device.BeginInvokeOnMainThread chamadas.

Um alerta com await

Uma abordagem mais direta envolve as async palavras-chave e await introduzidas no C# 5. O exemplo AlertAwait demonstra seu uso.

Um alerta sem nada

Se o método assíncrono retornar Task em vez de Task<TResult>, o programa não precisará usar nenhuma dessas técnicas se não precisar saber quando a tarefa assíncrona será concluída. O exemplo NothingAlert demonstra isso.

Salvando configurações do programa de forma assíncrona

O exemplo SaveProgramChanges demonstra o uso do SavePropertiesAsync método de para salvar as configurações do Application programa como eles mudam sem substituir o OnSleep método.

Um temporizador independente de plataforma

É possível usar Task.Delay para criar um temporizador independente de plataforma. O exemplo TaskDelayClock demonstra isso.

Entrada/saída de arquivos

Tradicionalmente, o namespace .NET System.IO tem sido a fonte do suporte de E/S de arquivo. Embora alguns métodos nesse namespace ofereçam suporte a operações assíncronas, a maioria não. O namespace também oferece suporte a várias chamadas de método simples que executam funções sofisticadas de E/S de arquivo.

Boas e más notícias

Todas as plataformas suportadas pelo Xamarin.Forms armazenamento local do aplicativo oferecem suporte — armazenamento privado para o aplicativo.

As bibliotecas Xamarin.iOS e Xamarin.Android incluem uma versão do .NET que o Xamarin adaptou expressamente para essas duas plataformas. Isso inclui classes das quais você pode usar para executar E/S de System.IO arquivo com armazenamento local de aplicativo nessas duas plataformas.

No entanto, se você procurar por essas System.IO classes em uma Xamarin.Forms PCL, não as encontrará. O problema é que a Microsoft renovou completamente a E/S de arquivo para a API do Tempo de Execução do Windows. Programas destinados ao Windows 8.1, Windows Phone 8.1 e à Plataforma Universal do Windows não são usados System.IO para E/S de arquivos.

Isso significa que você precisará usar o (discutido DependencyService pela primeira vez no Capítulo 9. Chamadas de API específicas da plataforma para implementar E/S de arquivo.

Observação

As bibliotecas de classe portáteis foram substituídas por bibliotecas do .NET Standard 2.0 e o .NET Standard 2.0 oferece suporte System.IO a tipos para todas as Xamarin.Forms plataformas. Não é mais necessário usar um para a maioria das tarefas de DependencyService E/S de arquivo. Consulte Tratamento de arquivos para Xamarin.Forms obter uma abordagem mais moderna para E/S de arquivos.

Uma primeira chance de E/S de arquivos entre plataformas

O exemplo TextFileTryout define uma IFileHelper interface para E/S de arquivo e implementações dessa interface em todas as plataformas. No entanto, as implementações do Tempo de Execução do Windows não funcionam com os métodos nessa interface porque os métodos de E/S de arquivo do Tempo de Execução do Windows são assíncronos.

Acomodando E/S de arquivo do Tempo de Execução do Windows

Os programas executados no Tempo de Execução do Windows usam classes no Windows.Storage e Windows.Storage.Streams namespaces para E/S de arquivo, incluindo o armazenamento local do aplicativo. Como a Microsoft determinou que qualquer operação que exija mais de 50 milissegundos deve ser assíncrona para evitar o bloqueio do thread da interface do usuário, esses métodos de E/S de arquivo são principalmente assíncronos.

O código que demonstra essa nova abordagem estará em uma biblioteca para que possa ser usado por outros aplicativos.

Bibliotecas específicas da plataforma

É vantajoso armazenar código reutilizável em bibliotecas. Isso é obviamente mais difícil quando diferentes partes do código reutilizável são para sistemas operacionais totalmente diferentes.

A Xamarin.Formssolução Book.Platform demonstra uma abordagem. Esta solução contém sete projetos diferentes:

Todos os projetos de plataforma individuais (com exceção de Xamarin.FormsBook.Platform.WinRT) têm referências a Xamarin.FormsBook.Platform. Os três projetos do Windows têm uma referência a Xamarin.FormsBook.Platform.WinRT.

Todos os projetos contêm um método estático Toolkit.Init para garantir que a biblioteca seja carregada se não for referenciada diretamente por um projeto em uma Xamarin.Forms solução de aplicativo.

O Xamarin.Formsprojeto Book.Platform contém a nova IFileHelper interface. Todos os métodos agora têm nomes com Async sufixos e objetos de retorno Task .

O Xamarin.Formsprojeto Book.Platform.WinRT contém a FileHelper classe para o Tempo de Execução do Windows.

O Xamarin.Formsprojeto Book.Platform.iOS contém a FileHelper classe para iOS. Esses métodos agora devem ser assíncronos. Alguns dos métodos usam as versões assíncronas dos métodos definidos em StreamWriter e StreamReader: WriteAsync e ReadToEndAsync. Outros convertem um resultado em um Task objeto usando o FromResult método.

O Xamarin.Formsprojeto Book.Platform.Android contém uma classe semelhante FileHelper para Android.

O Xamarin.Formsprojeto Book.Platform também contém uma FileHelper classe que facilita o DependencyService uso do objeto.

Para usar essas bibliotecas, uma solução de aplicativo deve incluir todos os projetos na Xamarin.Formssolução Book.Platform e cada um dos projetos de aplicativo deve ter uma referência à biblioteca correspondente em Xamarin.FormsBook.Platform.

A solução TextFileAsync demonstra como usar as Xamarin.Formsbibliotecas Book.Platform . Cada um dos projetos tem uma chamada para Toolkit.Init. O aplicativo faz uso das funções de E/S de arquivo assíncronas.

Mantendo-o em segundo plano

Os métodos em bibliotecas que fazem chamadas para vários métodos assíncronos — como os WriteFileAsync e ReadFileASync métodos na classe do Tempo de Execução do Windows FileHelper — podem ser tornados um pouco mais eficientes usando o ConfigureAwait método para evitar alternar de volta para o thread da interface do usuário.

Não bloqueie o thread da interface do usuário!

Às vezes, é tentador evitar o uso de ContinueWith ou await usando a Result propriedade nos métodos. Isso deve ser evitado, pois pode bloquear o thread da interface do usuário ou até mesmo travar o aplicativo.

Seus próprios métodos aguardados

Você pode executar algum código de forma assíncrona passando-o para um dos Task.Run métodos. Você pode chamar Task.Run dentro de um método assíncrono que lida com parte da sobrecarga.

Os vários Task.Run padrões são discutidos a seguir.

O conjunto básico de Mandelbrot

Para desenhar o conjunto de Mandelbrot em tempo real, o Xamarin.Forms. A biblioteca do kit de ferramentas tem uma Complex estrutura semelhante à do System.Numerics namespace.

O exemplo MandelbrotSet tem um CalculateMandeblotAsync método em seu arquivo code-behind que calcula o conjunto básico de Mandelbrot em preto e branco e usa BmpMaker para colocá-lo em um bitmap.

Marcando o progresso

Para relatar o progresso de um método assíncrono, você pode instanciar uma Progress<T> classe e definir seu método assíncrono para ter um argumento do tipo IProgress<T>. Isso é demonstrado no exemplo MandelbrotProgress.

Cancelando o trabalho

Você também pode escrever um método assíncrono para ser cancelável. Você começa com uma classe chamada CancellationTokenSource. A Token propriedade é um valor do tipo CancellationToken. Isso é passado para a função assíncrona. Um programa chama o Cancel método de CancellationTokenSource (geralmente em resposta a uma ação do usuário) para cancelar a função assíncrona.

O método assíncrono pode verificar periodicamente a IsCancellationRequested propriedade de e sair se CancellationToken a propriedade for true, ou simplesmente chamar o ThrowIfCancellationRequested método, caso em que o método termina com um OperationCancelledException.

O exemplo MandelbrotCancellation demonstra o uso de uma função cancelável.

Um MVVM Mandelbrot

O exemplo MandelbrotXF tem uma interface de usuário mais extensa e é principalmente baseado em classes e MandelbrotModelMandelbrotViewModel e:

Captura de tela tripla de Mandelbrot X F

Voltar para a Web

A WebRequest classe usada em alguns exemplos usa um protocolo assíncrono antiquado chamado Modelo de Programação Assíncrona ou APM. Você pode converter tal classe para o protocolo TAP moderno usando um dos FromAsync métodos na TaskFactory classe. O exemplo ApmToTap demonstra isso.