2013-08-13 3 views
3

나는 차가운 (시작되지 않은) 작업을 사용하여 비싼 것을 여러 번 실행하지 않는 캐싱 클래스를 가지고 있습니다. 당신의 작업은 실제로 지금은 TaskExtensions.Unwrap() 않습니다 정확히 내가 Task<T>Task<Task<T>>를 돌려 필요하지만처럼 보이는콜드 작업과 TaskExtensions.Unwrap

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

람, C# 5의 await을 사용하여 구현 될 때까지이 바로 좋은 작품

public class AsyncConcurrentDictionary<TKey, TValue> : System.Collections.Concurrent.ConcurrentDictionary<TKey, Task<TValue>> 
{ 
    internal Task<TValue> GetOrAddAsync(TKey key, Task<TValue> 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; 
    } 
} 

반환하는 래퍼가 실제로 Start()을 지원하지 않는 것 같습니다. 예외가 발생합니다.

TaskCompletionSource (약간 특별한 작업 요구 사항을 위해 필자에게 간행)에는 이런 종류의 일을위한 시설이없는 것 같습니다.

"콜드 작업"을 지원하는 TaskExtensions.Unwrap()의 대안이 있습니까?

+0

왜 당신이 당신의 질문을 바꿔하지? 나는 그것을 여러 번 읽었으며 아직도 당신이 달성하기를 원하는 것을 이해할 수 없습니다. 어쩌면 아직 답을 얻지 못했던 다른 사람들의 경우도 마찬가지 일 것입니다. – Ehsan

+0

당신은 이해하지 못하는 부분입니까? 'Task.Unwrap'은 이미 시작된 "Promise 스타일"작업을 반환하는 반면,'Task' 인스턴스는 캐시에서 합칠 수 있도록 unstarted해야합니다. – Fowl

답변

5

당신이 할 필요가 주위를 풀기 전에 Task을 유지하고 시작하는 것입니다

public Task<TValue> GetOrAddAsync(TKey key, Func<Task<TValue>> taskFunc) 
{ 
    Task<Task<TValue>> wrappedTask = new Task<Task<TValue>>(taskFunc); 
    Task<TValue> unwrappedTask = wrappedTask.Unwrap(); 

    Task<TValue> cachedTask = base.GetOrAdd(key, unwrappedTask); 

    if (cachedTask == unwrappedTask) 
     wrappedTask.Start(); 

    return cachedTask; 
} 

사용법 :

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