Estoy convirtiendo un poco de código async/await en tareas encadenadas, por lo que puedo usarlo en el marco publicado. El código Await se parece a estoEncadenamiento de tareas sin TaskCompletionSource?
public async Task<TraumMessage> Get() {
var message = await Invoke("GET");
var memorized = await message.Memorize();
return memorized;
}
donde
Task<TraumMessage> Invoke(string verb) {}
Task<TraumMessage> Memorize() {}
Tenía la esperanza de cadena Invoke
y Memorize
volver a la tarea producida por Memorize
, pero que resulta en un Task<Task<TraumMessage>
. La solución que he terminado es un TaskCompletionSource<TraumMessage>
como mi señal:
public Task<TraumMessage> Get() {
var completion = new TaskCompletionSource<TraumMessage>();
Invoke("GET").ContinueWith(t1 => {
if(t1.IsFaulted) {
completion.SetException(t1.Exception);
return;
}
t1.Result.Memorize().ContinueWith(t2 => {
if(t2.IsFaulted) {
completion.SetException(t2.Exception);
return;
}
completion.SetResult(t2.Result);
});
});
return completion.Task;
}
¿Hay una manera de lograr esto sin la TaskCompletionSource
?
Gracias a la serie EduAsync de Jon Skeet, he mirado bajo el capó de async/await y básicamente construye una clase que ejecuta una máquina de estado. Ya he usado ese enfoque antes, pero es aún más tedioso que el enfoque TCS. –
Ah, bueno, pensé en esto un montón más y simplemente no hay forma de continuar puro a menos que quieras bloquear la continuación de la primera tarea esperando el resultado de la continuación de la segunda tarea. Si las estrellas estuvieran alineadas, el robo de trabajo podría significar que hay muy poca sobrecarga, pero dado que teóricamente no tienes idea de cómo se creó la segunda tarea (podría ser un programador de tareas totalmente diferente o APM por ejemplo) no hay garantías para eso. Entonces debes asumir que estarías bloqueando un hilo esperando el resultado. Si quieres ver lo que quiero decir, házmelo saber y actualizaré mi respuesta. –
En http://blogs.msdn.com/b/pfxteam/archive/2010/11/21/10094564.aspx Stephen Taub envuelve el 'TaskCompletionSource' en un método auxiliar llamado 'Then' para implementar este patrón. – Govert