问题描述
我有一个使用冷(未开始)任务,以避免多次运行这么贵的东西缓存类。
I've got a caching class that uses cold (unstarted) tasks to avoid running the expensive thing multiple times.
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的等待
,ALA
This works great right up until your task is actually implemented using C#5's await
, ala
cache.GetOrAddAsync("key", new Task(async () => {
var r = await AsyncOperation();
return r.FastSynchronousTransform();
}));)`
现在,它看起来像 TaskExtensions.Unwrap()
不正是我需要通过转动任务&LT;任务&LT; T&GT;&GT;
到任务&LT; T&GT;
,但似乎包装返回实际上并不支持开始()
- 它抛出一个异常。
Now it looks like TaskExtensions.Unwrap()
does exactly what I need by turning Task<Task<T>>
into a Task<T>
, but it seems that wrapper it returns doesn't actually support Start()
- it throws an exception.
TaskCompletionSource
(我去为小幅特殊任务需要)似乎并没有对这样的事情任何设施,无论是。
TaskCompletionSource
(my go to for slightly special Task needs) doesn't seem to have any facilities for this sort of thing either.
有没有 TaskExtensions.Unwrap替代()
支持冷任务?
推荐答案
所有你需要做的是保持工作
各地展开,并开始之前:
All you need to do is to keep the Task
before unwrapping it around and start that:
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();
});
这篇关于冷任务和TaskExtensions.Unwrap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!