Pergunta

A Microsoft anunciou o CTP assíncrono do Visual Studio hoje (28 de outubro de 2010) que apresenta o async e await palavras-chave em C#/VB para execução de método assíncrono.

Primeiro pensei que o compilador traduzisse as palavras-chave na criação de um thread, mas de acordo com o papel branco e Anders Hejlsberg Apresentação do CDP (às 31h) a operação assíncrona acontece completamente na thread principal.

Como posso executar uma operação em paralelo no mesmo thread?Como isso é tecnicamente possível e para que o recurso é realmente traduzido em IL?

Foi útil?

Solução

Funciona de forma semelhante ao yield return palavra-chave em C# 2.0.

Um método assíncrono não é na verdade um método sequencial comum.Ele é compilado em uma máquina de estados (um objeto) com algum estado (variáveis ​​locais são transformadas em campos do objeto).Cada bloco de código entre dois usos de await é uma “etapa” da máquina de estado.

Isso significa que quando o método é iniciado, ele apenas executa o primeiro passo e então a máquina de estados retorna e agenda algum trabalho a ser feito - quando o trabalho estiver concluído, ele executará o próximo passo da máquina de estados.Por exemplo este código:

async Task Demo() { 
  var v1 = foo();
  var v2 = await bar();
  more(v1, v2);
}

Seria traduzido para algo como:

class _Demo {
  int _v1, _v2;
  int _state = 0; 
  Task<int> _await1;
  public void Step() {
    switch(this._state) {
    case 0: 
      this._v1 = foo();
      this._await1 = bar();
      // When the async operation completes, it will call this method
      this._state = 1;
      op.SetContinuation(Step);
    case 1:
      this._v2 = this._await1.Result; // Get the result of the operation
      more(this._v1, this._v2);
  }
}

O importante é que ele apenas usa o SetContinuation para especificar que quando a operação for concluída, ele deve chamar o Step método novamente (e o método sabe que deve executar o segundo bit do código original usando o _state campo).Você pode facilmente imaginar que o SetContinuation seria algo como btn.Click += Step, que seria executado completamente em um único thread.

O modelo de programação assíncrona em C# é muito próximo dos fluxos de trabalho assíncronos em F# (na verdade, é essencialmente a mesma coisa, exceto alguns detalhes técnicos) e escrever aplicativos GUI reativos de thread único usando async é uma área bastante interessante - pelo menos penso que sim - veja por exemplo Este artigo (talvez eu devesse escrever uma versão C# agora :-)).

A tradução é semelhante aos iteradores (e yield return) e, de fato, era possível usar iteradores para implementar programação assíncrona em C# anteriormente.escrevi um artigo sobre isso há algum tempo - e acho que ainda pode lhe dar algumas dicas sobre como funciona a tradução.

Outras dicas

Como posso ter uma operação executada em paralelo no mesmo thread?

Você não pode. A assincronia não é "paralelismo" ou "concorrência". A assincronia pode ser implementada com o paralelismo, ou pode não ser. Pode ser implementado dividindo o trabalho em pequenos pedaços, colocando cada pedaço de trabalho em uma fila e executando cada pedaço de trabalho sempre que o tópico não estiver fazendo mais nada.

Eu tenho toda uma série de artigos no meu blog sobre como tudo isso funciona; O único alemão diretamente para esta pergunta provavelmente subirá na quinta -feira da próxima semana. Ver

http://blogs.msdn.com/b/ericlippert/archive/tags/async/

para detalhes.

Pelo que entendi, o que o async e await Palavras -chave fazem é que toda vez que um async O método emprega o await Palavra -chave, o compilador transformará o restante do método em uma continuação programada quando a operação assíncrona for concluída. Que permite async Métodos para retornar ao chamador imediatamente e retomar o trabalho quando a parte assíncrona for concluída.

De acordo com os documentos disponíveis, há muitos detalhes, mas, a menos que eu esteja enganado, essa é a essência disso.

A ver com o objetivo dos métodos assíncronos não é executar muito código em paralelo, mas cortar os métodos assíncronos em vários pequenos pedaços, que podem ser chamados conforme necessário. O ponto principal é que o compilador lidará com toda a fiação complexa de retornos de chamada usando tarefas/continuações. Isso não apenas reduz a complexidade, mas permite que o método Async seja escrito mais ou menos como o código síncrono tradicional.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top