Estou tentando há um tempo algo que achei que seria simples trabalhar com .NET 4.5
Quero iniciar duas tarefas de longa duração ao mesmo tempo e coletar os
resultados da melhor maneira C # 4.5 (RTM)
O seguinte funciona, mas não gosto porque:
- Eu quero
Sleep
ser um método assíncrono para que possaawait
outros métodos - Parece desajeitado com
Task.Run()
- Não acho que isso esteja usando novos recursos de linguagem!
Código de trabalho:
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Task.Run(() => Sleep(5000));
var task2 = Task.Run(() => Sleep(3000));
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for a total of " + totalSlept + " ms");
}
private static int Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
Console.WriteLine("Sleeping for " + ms + " FINISHED");
return ms;
}
Código não funcional:
Atualização: Isso realmente funciona e é a maneira correta de fazer isso, o único problema é o Thread.Sleep
Este código não funciona porque a chamada para Sleep(5000)
inicia imediatamente a execução da tarefa, portanto, Sleep(1000)
não é executada até que seja concluída. Isto é verdade mesmo que Sleep
é async
e eu não estou usando await
ou chamar .Result
muito cedo.
Eu pensei que talvez houvesse uma maneira de obter uma não execução Task<T>
chamando um async
método para que eu pudesse chamar Start()
as duas tarefas, mas não consigo descobrir como obter um Task<T>
chamando um método assíncrono.
public static void Go()
{
Console.WriteLine("Starting");
var task1 = Sleep(5000); // blocks
var task2 = Sleep(1000);
int totalSlept = task1.Result + task2.Result;
Console.WriteLine("Slept for " + totalSlept + " ms");
}
private static async Task<int> Sleep(int ms)
{
Console.WriteLine("Sleeping for " + ms);
Thread.Sleep(ms);
return ms;
}
fonte
task1.Result
não emvar task1 = Sleep(5000)
porque seu método Sleep sem uma palavra-chave await é síncrono.Respostas:
Você deve usar Task.Delay em vez de Sleep para programação assíncrona e, em seguida, usar Task.WhenAll para combinar os resultados da tarefa. As tarefas seriam executadas em paralelo.
fonte
fonte
Go
método do chamador é síncrono, mas deseja concluir duas tarefas independentes de forma assíncrona (ou seja, nenhuma precisa ser concluída antes da outra, mas ambas devem ser concluídas antes que a execução continue), entãoTask.WaitAll
seria melhor, e você não não precisa da palavra-chave await, portanto, não é necessário que oGo
método de chamada seja assíncrono. Nenhuma das abordagens é melhor, é apenas uma questão de qual é o seu objetivo.async void LongTask1() {...}
Método nulo : não tem propriedade Task.Result. Use Task sem T em tal caso:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
e agora entendit1.Result
.<TResult>
é o tipo de retorno do seu resultado. Você precisará de umreturn <TResult>
em seu método para que isso funcione.t1
e ast2
variáveis, você pode usarnew Task(...)
. Por exemplo:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Uma pegadinha dessa abordagem é que o compilador não reconhecerá que a variável foi atribuída e a tratará como não atribuída se você não fornecer um valor inicial.Embora seu
Sleep
método seja assíncrono,Thread.Sleep
não é. A ideia do assíncrono é reutilizar um único thread, não iniciar vários threads. Como você bloqueou usando uma chamada síncrona para Thread.Sleep, não vai funcionar.Estou assumindo que
Thread.Sleep
é uma simplificação do que você realmente deseja fazer. Sua implementação real pode ser codificada como métodos assíncronos?Se você precisar executar várias chamadas de bloqueio síncronas, procure outro lugar, eu acho!
fonte
var x = y()
e nãovar x=await y()
ouy().wait()
ainda espere todo o caminho e se o async não resolver isso sozinho, o que devo fazer? NOTE que y é decorado com assíncrono e espero que faça tudo dentro de quando tudo, não exatamente onde foi atribuído, EDITAR: Eu apenas quando meu parceiro disse, vamos tentarTask.Factory
, e ele disse que funcionou quando eu sair lado desta classePara responder a este ponto:
você pode reescrever a
Sleep
função desta forma:executar este código resultará em:
fonte
É fim de semana agora!
fonte
Este artigo ajudou a explicar muitas coisas. É no estilo FAQ.
Async / Await FAQ
Esta parte explica porque
Thread.Sleep
é executado no mesmo thread original - levando à minha confusão inicial.fonte