He estado intentando durante un tiempo conseguir algo que pensé que sería sencillo trabajar con .NET 4.5
Quiero iniciar dos tareas de ejecución prolongada al mismo tiempo y recopilar los
resultados de la mejor manera C # 4.5 (RTM)
Lo siguiente funciona pero no me gusta porque:
- Quiero
Sleep
ser un método asincrónico para que puedaawait
otros métodos - Simplemente se ve torpe con
Task.Run()
- ¡No creo que esto esté usando ninguna característica de idioma nueva en absoluto!
Código de trabajo:
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 que no funciona:
Actualización: esto realmente funciona y es la forma correcta de hacerlo, el único problema es el Thread.Sleep
Este código no funciona porque la llamada a Sleep(5000)
inicia inmediatamente la ejecución de la tarea, por lo Sleep(1000)
que no se ejecuta hasta que se completa. Esto es cierto a pesar de que lo Sleep
es async
y no estoy usando await
o llamando .Result
demasiado pronto.
Pensé que tal vez había una manera de hacer que no se ejecutara Task<T>
llamando a un async
método para luego poder llamar Start()
a las dos tareas, pero no puedo averiguar cómo obtener una Task<T>
llamando a un método así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;
}
fuente
task1.Result
not atvar task1 = Sleep(5000)
porque su método Sleep sin una palabra clave await es sincrónico.Respuestas:
Debe usar Task.Delay en lugar de Sleep para la programación asincrónica y luego usar Task.WhenAll para combinar los resultados de la tarea. Las tareas se ejecutarían en paralelo.
fuente
fuente
Go
método de la persona que llama es sincrónico, pero desea completar dos tareas independientes de forma asincrónica (es decir, ninguna debe completarse antes que la otra, pero ambas deben completarse antes de que continúen las ejecuciones), entoncesTask.WaitAll
sería mejor, y no No necesita la palabra clave await, por lo que no es necesario que elGo
método de llamada sea asíncrono. Ninguno de los enfoques es mejor, es solo una cuestión de cuál es tu objetivo.async void LongTask1() {...}
Método vacío: no tiene propiedad Task.Result. Tarea utilizar sin T en tal caso:async Task LongTask1()
.Task<TResult> t1 = LongTask1();
y ahora lo tengot1.Result
.<TResult>
es el tipo de retorno de su resultado. Necesitará unreturn <TResult>
método en su método para que esto funcione.t1
y last2
variables, puede usarnew Task(...)
. Por ejemplo:int int1 = 0; await Task.WhenAll(new Task(async () => { int1 = await LongTask1(); }));
. Un inconveniente de este enfoque es que el compilador no reconocerá que la variable fue asignada y la tratará como no asignada si no le da un valor inicial.Si bien su
Sleep
método es asíncrono,Thread.Sleep
no lo es. La idea general de async es reutilizar un solo hilo, no iniciar varios hilos. Debido a que ha bloqueado el uso de una llamada sincrónica a Thread.Sleep, no va a funcionar.Estoy asumiendo que
Thread.Sleep
es una simplificación de lo que realmente quiere hacer. ¿Se puede codificar su implementación real como métodos asíncronos?Si necesita ejecutar múltiples llamadas de bloqueo sincrónico, ¡busque en otro lado, creo!
fuente
var x = y()
y novar x=await y()
oy().wait()
todavía espere todo el tiempo, y si async no maneja eso por sí solo, ¿qué debo hacer? TENGA EN CUENTA que y está decorado con async, y espero que haga todo dentro del when all, no justo en el lugar donde está asignado, EDITAR: justo cuando le dije a mi compañero, intentemosTask.Factory
, y él dijo que funcionó cuando salí lado de esta clasePara responder a este punto:
tal vez puedas reescribir la
Sleep
función así:ejecutar este código dará como resultado:
fuente
¡Es fin de semana ahora!
fuente
Este artículo ayudó a explicar muchas cosas. Tiene un estilo de preguntas frecuentes.
Preguntas frecuentes de Async / Await
Esta parte explica por qué se
Thread.Sleep
ejecuta en el mismo hilo original, lo que lleva a mi confusión inicial.fuente