我有一个缓存类,它使用冷(未启动)任务来避免多次运行昂贵的任务。
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;
}
}在使用C#5的await,ala实现任务之前,这是非常好的工作。
cache.GetOrAddAsync("key", new Task(async () => {
var r = await AsyncOperation();
return r.FastSynchronousTransform();
}));)`现在看来,TaskExtensions.Unwrap()通过将Task<Task<T>>转换为Task<T>来做我所需要的事情,但是它返回的包装器似乎实际上并不支持Start() --它会抛出一个异常。
TaskCompletionSource (我的目标是满足一些特殊的任务需求)似乎也没有任何类似的工具。
是否有一种替代TaskExtensions.Unwrap()来支持“冷任务”?
发布于 2013-08-13 09:19:26
您所需要做的就是在展开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();
});https://stackoverflow.com/questions/18201247
复制相似问题