Cold Task e TaskExtensions.Unwrap

Ho una class di memorizzazione nella cache che utilizza attività fredde (non avviate) per evitare di eseguire la cosa costosa più volte.

public class AsyncConcurrentDictionary : System.Collections.Concurrent.ConcurrentDictionary<TKey, Task> { internal Task GetOrAddAsync(TKey key, Task newTask) { var cachedTask = base.GetOrAdd(key, newTask); if (cachedTask == newTask && cachedTask.Status == TaskStatus.Created) // We won! our task is now the cached task, so run it cachedTask.Start(); return cachedTask; } } 

Funziona benissimo fino a quando il tuo compito non viene effettivamente implementato usando l’ await del C # 5, ala

 cache.GetOrAddAsync("key", new Task(async () => { var r = await AsyncOperation(); return r.FastSynchronousTransform(); }));)` 

Ora sembra TaskExtensions.Unwrap() fa esattamente ciò di cui ho bisogno trasformando Task<Task> in un’attività Task , ma sembra che il wrapper restituito non supporti effettivamente Start() – genera un’eccezione .

TaskCompletionSource (le mie esigenze di task leggermente speciali) non sembra avere alcuna possibilità per questo genere di cose.

Esiste un’alternativa a TaskExtensions.Unwrap() che supporta “cold task”?

Tutto ciò che devi fare è mantenere l’ Task prima di scartarla e iniziare così:

 public Task GetOrAddAsync(TKey key, Func> taskFunc) { Task> wrappedTask = new Task>(taskFunc); Task unwrappedTask = wrappedTask.Unwrap(); Task cachedTask = base.GetOrAdd(key, unwrappedTask); if (cachedTask == unwrappedTask) wrappedTask.Start(); return cachedTask; } 

Uso:

 cache.GetOrAddAsync( "key", async () => { var r = await AsyncOperation(); return r.FastSynchronousTransform(); });