[C#] Prática de Programação Paralela: Noções Básicas de Programação Assíncrona Baseada em Tarefas (Parte 1)

        O Capítulo 8 apresenta as práticas e soluções disponíveis para programação assíncrona em C# e também discute quando é apropriado usar programação assíncrona. Este capítulo apresenta principalmente as palavras-chave async e await.

        Na verdade, em estudos anteriores, todos já entenderam essas duas palavras-chave e as utilizaram muito. Na verdade, acho que não há necessidade de entrar em detalhes, mas vamos dar uma breve olhada aqui.

        Aprenda Engenharia com este Tutorial: Magician Dix/HandsOnParallelProgramming · GitCode

        Devido às limitações de espaço, este artigo é o primeiro, cujo conteúdo principal são as palavras-chave async e await e a implementação manual do TAP.


1. Sobre as palavras-chave async e await

        Usando as palavras-chave async e await, o código pode manter o estado da implementação síncrona com apenas pequenas alterações.

1.1. Modo assíncrono baseado em eventos

        A forma mais original de escrever é o Event-Based Asynchronous Pattern (EAP), que requer o registro de retornos de chamada para implementar operações assíncronas. O exemplo de código é o seguinte:

        public static void WebClientSample()
        {
            Debug.Log("WebClientSample ,Start !");
            WebClient client = new WebClient();
            client.DownloadStringCompleted += OnWebClientDownloaded;
            client.DownloadStringAsync(new Uri("https://blog.csdn.net/cyf649669121"));
            Debug.Log("WebClientSample ,开始下载!");
        }

        private static void OnWebClientDownloaded(object sender, DownloadStringCompletedEventArgs e)
        {
            if (e.Error != null)
            {
                Debug.LogError($"下载失败 : {e.Error.Message}");
                return;
            }

            Debug.Log("下载成功");
            Debug.Log(e.Result);
        }

        O resultado da execução deste trecho de código é o seguinte:

         Pode-se ver que as operações assíncronas são realmente implementadas, mas devido ao método de escrita baseado em eventos, dividimos o código em duas partes. Em alguns casos, esta forma de escrever é conveniente e lógica. Mas quando nossa operação assíncrona é de natureza processual, essa forma de escrever é mais complicada: precisamos conectar métodos em série para realizar o processo.

1.2. Modo assíncrono baseado em tarefas

        Transformamos o código acima em um modo assíncrono baseado em tarefas:

        private void RunWithWebClientInTask()
        {
            WebClientInTask();
            Debug.Log("RunWithWebClientInTask End !");
        }

        public static async Task WebClientInTask()
        {
            Debug.Log("开始异步任务下载!");
            WebClient client = new WebClient();
            var result = await client.DownloadStringTaskAsync(new Uri("https://blog.csdn.net/cyf649669121"));
            Debug.Log("下载成功");
            Debug.Log(result);
        }

        Usando as palavras-chave async e await, o modo EAP é óbvio. Porém, não creio que haja vantagem ou desvantagem absoluta entre os dois, tudo depende dos cenários de uso de cada um.

        Os resultados da execução são os seguintes:

         Pode-se observar que o thread principal ainda não está bloqueado e o assíncrono também é alcançado. Quando nosso método contém a palavra-chave async, ele fornece instruções ao compilador de que o método será executado de forma assíncrona (await) quando necessário.

1.3. Tipo retornado pelo método assíncrono

        Os métodos assíncronos têm três tipos de retorno: void, Task e Task<T>. Todos os métodos assíncronos devem retornar Task to wait (usando a palavra-chave await).Eles não retornarão imediatamente quando chamados, mas aguardarão pela execução assíncrona. O método void indica que você não deseja esperar e chamar o método não será bloqueado.

        Escreva um exemplo aqui:

        public static async void WaitWithoutTask()
        {
            Debug.Log("WaitWithoutTask Start !");
            await Task.Delay(1000);
            Debug.Log("WaitWithoutTask End !");
        }

        public static async Task WaitWithTask()
        {
            Debug.Log("WaitWithTask Start !");
            await Task.Delay(1000);
            Debug.Log("WaitWithTask End !");
        }

        Há uma diferença no valor de retorno entre esses dois códigos, mas a diferença ao utilizá-lo é que ao retornar para Task, você pode escolher se deseja aguardar a conclusão da execução (use await), mas ao retornar para void, você não pode esperar .

2. Implementar TAP manualmente

        Na verdade, no Capítulo 2: Paralelismo de Tarefas, discutimos como usar a classe Task para implementar análise assíncrona baseada em tarefas (TAP). Ao usar a palavra-chave async, o compilador realizará as otimizações necessárias, o que é muito conveniente. Aqui apresentamos como implementar o TAP manualmente.

TaskCompletionSource representa o lado do produtor de um Task<TResult> que não está vinculado ao delegado e fornece acesso ao lado do consumidor por meio da propriedade Task. https://learn.microsoft.com/zh-cn/dotnet/api/system.threading.tasks.taskcompletionsource-1?view=netstandard-2.1Aqui         usaremos a classe TaskCompletionSource<T>:

        public static Task<int> MyTaskResult()
        {
            TaskCompletionSource<int> taskCompletionSource = new TaskCompletionSource<int>();
            Thread.Sleep(1000);//会阻塞调用线程
            taskCompletionSource.SetResult(555);
            return taskCompletionSource.Task;
        }

        Do ponto de vista da escrita, é melhor usar Task diretamente e não há outras vantagens.


        (Continua)

         Aprenda Engenharia com este Tutorial: Magician Dix/HandsOnParallelProgramming · GitCode

Acho que você gosta

Origin blog.csdn.net/cyf649669121/article/details/131838459
Recomendado
Clasificación