Pergunta

Eu tenho algumas coisas escrito em C # que executa o código concorrente, fazendo uso intenso da biblioteca paralela de tarefas (Task e cadeias de continuação futuro).

Agora estou portar isso para F # e estou tentando descobrir os prós e contras do uso F # Async fluxos de trabalho vs. as construções no TPL. Estou inclinado para TPL, mas acho que isso poderia ser feito de qualquer maneira.

Alguém tem dicas e sabedoria sobre como escrever programas concorrentes em F # para mostrar?

Foi útil?

Solução

O nome resume muito bem a diferença: assíncrona programação vs. paralelo programação. Mas na F # você pode misturar e combinar.

F # assíncronos Workflows

F workflows # assíncronos são úteis quando você quer ter código de executar de forma assíncrona, que está começando uma tarefa e não ficar esperando para o resultado final. O uso mais comum é operações de IO. Ter seu fio sentar lá em um loop ocioso de espera para o seu disco rígido para terminar de escrever desperdiça recursos.

Se você começou a operação de gravação assíncrona você pode suspender o fio e tê-lo acordado mais tarde por uma interrupção de hardware.

biblioteca paralela de tarefas

A biblioteca paralela de tarefas em .NET 4.0 abstrai a noção de uma tarefa - como a decodificação de um MP3, ou ler alguns resultados de um banco de dados. Nessas situações, você realmente deseja que o resultado do cálculo e, em algum ponto no tempo mais tarde estão à espera para o resultado da operação. (Ao acessar a propriedade .Result.)

Você pode facilmente misturar e combinar esses conceitos. Tais como fazer todas as suas operações de IO em um objeto TPL tarefas. Para o programador de ter resumido a necessidade de 'acordo com a' esse segmento extra, mas debaixo das cobertas você está o desperdício de recursos.

Como sábio você pode criar uma série de F workflows # assíncronos e executá-los em paralelo (Async.Parallel), mas então você precisa esperar o resultado final (Async.RunSynchronously). Isso você liberta da necessidade de iniciar explicitamente todas as tarefas, mas na verdade você está apenas realizando a computação em paralelo.

Na minha experiência, eu acho que o TPL é mais útil porque geralmente eu quero executar operações N em paralelo. No entanto, F workflows # assíncronos são ideais quando há algo que está acontecendo 'nos bastidores', como um tipo de coisa Reactive Agente ou caixa de correio. (Você enviar algo uma mensagem, ela processa e envia-lo de volta.)

Espero que ajude.

Outras dicas

Na 4.0, eu diria:

  • Se a sua função é sequencial, o uso assíncrono fluxos de trabalho. Eles simplesmente ler melhor.
  • Use o TPL para tudo o resto.

Também é possível misturar e combinar. Eles adicionaram suporte para executar um fluxo de trabalho como uma tarefa e criar tarefas que seguem o assíncrono Begin padrão / End usando TaskFactory.FromAsync , o equivalente TPL de Async.FromBeginEnd ou Async.BuildPrimitive.

let func() =
    let file = File.OpenRead("foo")
    let buffer = Array.zeroCreate 1024
    let task1 = Task.Factory.FromAsync(file.BeginRead(buffer, 0, buffer.Length, null, null), file.EndRead)
    task1.Start()

    let task2 = Async.StartAsTask(file.AsyncRead(1024))
    printfn "%d" task2.Result.Length

É importante notar também que tanto o tempo de execução assíncrono fluxos de trabalho e do TPL está indo para criar um núcleo adicional primitivo (um evento) e uso WaitForMultipleObjects para rastrear I / O de conclusão, em vez de utilizar portas de conclusão e as chamadas de retorno. Isso é indesejável em algumas aplicações.

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