asynchronous aguardar e segmentação

com base no que li no MSDN

As palavras-chave async e await não fazem com que threads adicionais sejam criados. Métodos asynchronouss não requerem multithreading porque um método asynchronous não é executado em seu próprio segmento. O método é executado no contexto de synchronization atual e usa o tempo no encadeamento apenas quando o método está ativo. Você pode usar Task.Run para mover o trabalho vinculado à CPU para um thread de segundo plano, mas um thread em segundo plano não ajuda com um processo que está apenas aguardando a disponibilização dos resultados.

É basicamente dizendo que nenhum segmento será criado. Mas dentro de uma class que eu herdei o HttpClient eu encontrei algo interessante ..

 async Task SendAsync(HttpMethod method, Uri uri, HttpContent content, CancellationToken cancellationToken) { HttpRequestMessage msg = new HttpRequestMessage(method, uri); msg.Content = content; //On Main Thread HttpResponseMessage response = await SendAsync(msg, cancellationToken); //On worker thread //... } 

o método é chamado dentro de static void Main

 Task result = client.GetAsync(...); //GetAsync calls await SendAsync result.Wait(); 

Por que estou em um segmento separado após await SendAsnc chamada await SendAsnc ? Eu pensei que o asyn não cria um novo tópico. Ou pelo menos será invocado de volta para o segmento original depois de esperar.

Isso é mal anunciado na documentação, mas a maneira como o async / await funciona em um aplicativo de console é muito diferente de como ele funciona em um aplicativo de UI devido à falta de um contexto de synchronization em um aplicativo de console. Este artigo descreve detalhes e fornece um exemplo de código de como adicionar um para que async / wait se comporte de uma maneira mais previsível.

Normalmente, você está absolutamente correto sobre async / wait não necessariamente envolvendo multithreading (embora coisas como Task.Run, na verdade, fazem com que o código em questão seja executado no pool de threads), mas (como descrito no artigo que eu associei a ) em um aplicativo de console async / wait pode rodar em qualquer lugar.

Minha analogia usual de como o asynchronous funciona ao executar o mesmo tópico é pensar em ir a um restaurante com outras 9 pessoas (o que significa 10 pessoas no total). Quando o garçom chega, nove pessoas estão prontas e a décima não está. Neste caso, o garçom pegará as outras 9 ordens das pessoas primeiro e depois voltará para a 10ª pessoa. Se por alguma razão a 10ª pessoa estiver realmente devagar, o garçom pode sempre trazer as ordens de volta para a cozinha e voltar quando a 10ª pessoa estiver pronta.

Claramente, não faz sentido trazer um segundo garçom apenas para esperar que o 10º cara esteja pronto para pedir, e seria claramente ineficiente fazer todos os outros esperarem que o cara esteja pronto. Adicionando garçons extras à situação não vai acelerar as coisas, porque o atraso não está sendo causado pela falta de garçons, é causado pelo fato de o 10º ser lento em decidir (e não há nada que a equipe de garçons possa fazer sobre isso ).

Eu descrevo esse comportamento na minha introdução ao post do blog async .

Em resumo, isso está correto:

As palavras-chave async e await não fazem com que threads adicionais sejam criados.

E assim é isto:

Eu pensei que o asyn não cria um novo tópico.

Isso não está correto:

Ou pelo menos será invocado de volta para o segmento original depois de esperar.

async e awaitpor si só – não causam nenhum encadeamento adicional a ser criado. No entanto, depois que um await concluído, o restante do método async deve ser executado em algum lugar .

Por padrão, await captura um “contexto”, que é o SynchronizationContext atual (a menos que seja null , caso em que o contexto atual é o TaskScheduler atual). Os encadeamentos de interface do usuário têm seu próprio contexto de synchronization (por exemplo, WinFormsSynchronizationContext ou DispatcherSynchronizationContext ) e, nesse caso, o método async continuará executando nesse mesmo encadeamento de interface do usuário.

Em um aplicativo Console, não há contexto de synchronization, portanto, o “contexto” capturado por await será o contexto do conjunto de encadeamentos. Assim, quando o método async está pronto para continuar, ele será agendado para o pool de threads e escolhido por algum thread lá.

Aplicativos de console têm um pool de threads SynchronizationContext em vez de um SynchronizationContext de um-pedaço de cada vez usado em GUI e ASP.Net Applications, portanto, quando o await for concluído, ele planeja o restante do método async em um thread de pool de threads . leia este artigo para obter mais informações sobre o comportamento de espera do async.