Pergunta

Em python, a palavra-chave yield pode ser usada em contextos push e pull, eu sei como fazer o contexto pull em c#, mas como conseguiria o push.Posto o código que estou tentando replicar em c# do python:

def coroutine(func):
  def start(*args,**kwargs):
    cr = func(*args,**kwargs)
    cr.next()
    return cr
  return start

@coroutine
def grep(pattern):
  print "Looking for %s" % pattern
  try:
    while True:
      line = (yield)
      if pattern in line:
        print line,
  except GeneratorExit:
    print "Going away. Goodbye"
Foi útil?

Solução

Se o que você deseja é uma "coleção observável" - ou seja, uma coleção que leva os resultados a você, em vez de deixar o consumidor puxá -los - então você provavelmente deseja analisar as extensões reativas da estrutura. Aqui está um artigo sobre ele:

http://www.infoq.com/news/2009/07/reactive-framework-linq-events

Agora, como você observa, você pode construir os iteradores de estilo "Push" e "Pull" facilmente se tiver coroutinas disponíveis. (Ou, como Thomas aponta, você também pode construí -los com continuações.) Na versão atual de C#, não temos coroutinas verdadeiras (ou continuações). No entanto, estamos muito preocupados com a dor dos usuários por perto programação assíncrona.

A implementação de coroutinas baseadas em fibra como recurso de linguagem de primeira classe é uma técnica que poderia ser usada para facilitar a programação assíncrona, mas essa é apenas uma idéia possível de muitos que estamos pesquisando atualmente. Se você tem um cenário impressionante realmente sólido, onde as Coroutinas fazem um trabalho melhor do que qualquer outra coisa - incluindo a estrutura reativa - então eu adoraria ouvir mais sobre isso. Quanto mais dados realistas temos sobre quais problemas reais as pessoas estão enfrentando em programação assíncrona, maior a probabilidade de encontrarmos uma boa solução. Obrigado!

Atualização: anunciamos recentemente que estamos adicionando fluxos de controle assíncronos semelhantes a coroutines à próxima versão do C# e VB. Você pode experimentar você mesmo com nossa edição de visualização de tecnologia comunitária, que você pode baixar aqui.

Outras dicas

C# não tem em geral co-rotinas.Uma co-rotina geral é onde a co-rotina tem sua própria pilha, ou seja,ele pode invocar outros métodos e esses métodos podem "gerar" valores.A implementação de corrotinas gerais requer fazer algumas coisas inteligentes com pilhas, possivelmente até e incluindo a alocação de quadros de pilha (as estruturas ocultas que contêm variáveis ​​locais) no heap.Isso pode ser feito, algumas linguagens fazem isso (por exemploEsquema), mas é um pouco complicado fazer isso direito.Além disso, muitos programadores acham o recurso difícil de entender.

Co-rotinas gerais podem ser emuladas com threads.Cada thread tem sua própria pilha.Em uma configuração de co-rotina, ambos os threads (o chamador inicial e o thread da co-rotina) alternarão o controle, eles nunca serão executados simultaneamente.O mecanismo de "rendimento" é então uma troca entre os dois threads e, como tal, é caro (sincronização, uma viagem de ida e volta através do kernel do sistema operacional e do agendador...).Além disso, há muito espaço para vazamentos de memória (a co-rotina deve ser explicitamente "parada", caso contrário, o thread em espera permanecerá para sempre).Assim, isso raramente é feito.

C# fornece um recurso de co-rotina bastardizado chamado iteradores.O compilador C# converte automaticamente o código do iterador em uma classe de estado específica, com variáveis ​​locais tornando-se campos de classe.O rendimento é então, no nível da VM, uma simples return.Tal coisa é possível desde que o "rendimento" seja executado a partir do próprio código do iterador, e não de um método que o código do iterador invoca.Os iteradores C# já cobrem muitos casos de uso e os projetistas de C# não estavam dispostos a ir mais longe para continuações.Algumas pessoas sarcásticas fazem questão de afirmar que a implementação de continuações completas teria impedido o C# de ser tão eficiente quanto seu arquiinimigo Java (continuações eficientes são viáveis, mas isso requer bastante trabalho com o GC e o compilador JIT).

Obrigado @nicklarsen, você me ajudou a lembrar as coisas novas que a MS introduziram, a interface IOBServable.

link http://msdn.microsoft.com/en-us/library/dd783449(vs.100).aspx

Na verdade, o .NET não faz "suposições incorretas" sobre a afinidade do encadeamento, na verdade, separa totalmente a noção de um encadeamento de nível .NET do encadeamento do nível do sistema operacional.

O que você precisa fazer é associar um estado lógico de fio .NET à sua fibra (para isso, você precisa das APIs de hospedagem CLR, mas não precisa escrever um host que você pode usar os necessários diretamente do seu próprio aplicativo) e tudo, tudo, Rastreamento de bloqueio, manuseio de exceção funciona normalmente novamente.

Um exemplo pode ser encontrado aqui: http://msdn.microsoft.com/en-us/magazine/cc164086.aspx

BTW Mono 2.6 contém suporte de corotagem de baixo nível e pode ser usado para implementar todas as primitivas de nível superior facilmente.

Eu adoraria ver uma API baseada em fibra para .Net.

Tentei usar a API de fibra nativa em C# por meio de p/invoke há algum tempo, mas como o tratamento de exceções do tempo de execução (incorretamente) faz suposições baseadas em threads, as coisas quebraram (muito) quando ocorreram exceções.

Um “aplicativo matador” para uma API de corrotina baseada em fibra é a programação de jogos;certos tipos de IA exigem um thread "leve" que você pode dividir o tempo à vontade.Por exemplo, as árvores de comportamento do jogo exigem a capacidade de “pulsar” o código de decisão a cada quadro, permitindo que o código de IA retorne cooperativamente ao chamador quando a fatia de decisão terminar.Isso é possível de implementar com threads rígidos, mas muito, muito mais complicado.

Portanto, embora os verdadeiros casos de uso de fibra não sejam convencionais, eles definitivamente existem, e um pequeno nicho de nós, codificadores .Net, aplaudiria fortemente se os bugs existentes no subsistema de fibra fossem resolvidos.

Bem, tentei desenvolver uma biblioteca completa para gerenciar coroutinas com apenas um único thread. A parte mais difícil era chamar coroutines dentro das coroutinas ... e retornar parâmetros, mas finalmente atingi um resultado muito bom aqui. O único aviso é que o bloqueio de operações de E/S deve ser feito através de tarefas e Alll "Return" deve ser substituído por "Returno de rendimento". Com o servidor de aplicativos com base nesta biblioteca, consegui quase o dobro das solicitações feitas com um assíncrono/aguardo padrão com base no IIS. (Procure Node.cs e Node.cs.musicstore no Github para experimentá -lo em casa)

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