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 aos 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 deverá ser relegado a threads secundários de execução.

Vários programas de amostra 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 é concluído. 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 o processamento assíncrono está disponível no .NET e no C#. Isso envolve as Task classes and Task<TResult> e outros tipos nos System.Threading namespaces and System.Threading.Tasks , bem como o C# 5.0 async e await as palavras-chave. É nisso que este capítulo se concentra.

De retornos de chamada para aguardar

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 retornados constituem uma "promessa" de que um valor do tipo TResult estará disponível quando a tarefa for concluída. O Task valor retornado 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 ignora a caixa de alerta.

Um alerta com retornos de chamada

O exemplo AlertCallbacks demonstra como lidar com 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 for concluída. O exemplo NothingAlert demonstra isso.

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

O exemplo SaveProgramChanges demonstra o uso do método de para salvar as SavePropertiesAsync configurações do Application programa à medida que elas são alteradas 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 arquivo

Tradicionalmente, o namespace .NET System.IO tem sido a fonte do suporte de E/S de arquivo. Embora alguns métodos neste namespace ofereçam suporte a operações assíncronas, a maioria não. O namespace também dá 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 de 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 que podem ser usadas para executar E/S de System.IO arquivo com armazenamento local de aplicativo nessas duas plataformas.

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

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 dá suporte a System.IO tipos para todas as Xamarin.Forms plataformas. Não é mais necessário usar a para a DependencyService maioria das tarefas de E/S de arquivo. Consulte Tratamento de arquivos para Xamarin.Forms obter uma abordagem mais moderna de E/S de arquivo.

Uma primeira tentativa de E/S de arquivo multiplataforma

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 do 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 em execução no Tempo de Execução do Windows usam classes nos Windows.Storage namespaces e Windows.Storage.Streams para E/S de arquivo, incluindo armazenamento local de 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 uso do DependencyService 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 bibliotecas Book.PlatformXamarin.Forms. Cada um dos projetos tem uma chamada para Toolkit.Init. O aplicativo usa as 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 métodos and ReadFileASync na classe Windows Runtime FileHelper — podem se tornar um pouco mais eficientes usando o ConfigureAwait método para evitar a alternância 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 aguardáveis

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 abaixo.

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 o 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 CancellationToken e sair se 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 do usuário mais extensa e é baseado principalmente em classes e MandelbrotModel MandelbrotViewModel :

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 APM ou Modelo de Programação Assíncrona. Você pode converter essa classe para o protocolo TAP moderno usando um dos FromAsync métodos da TaskFactory classe. O exemplo ApmToTap demonstra isso.