首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >冷任务与TaskExtensions.Unwrap

冷任务与TaskExtensions.Unwrap
EN

Stack Overflow用户
提问于 2013-08-13 05:21:25
回答 1查看 1.4K关注 0票数 4

我有一个缓存类,它使用冷(未启动)任务来避免多次运行昂贵的任务。

代码语言:javascript
复制
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实现任务之前,这是非常好的工作。

代码语言:javascript
复制
cache.GetOrAddAsync("key", new Task(async () => {
  var r = await AsyncOperation();
  return r.FastSynchronousTransform();
}));)`

现在看来,TaskExtensions.Unwrap()通过将Task<Task<T>>转换为Task<T>来做我所需要的事情,但是它返回的包装器似乎实际上并不支持Start() --它会抛出一个异常。

TaskCompletionSource (我的目标是满足一些特殊的任务需求)似乎也没有任何类似的工具。

是否有一种替代TaskExtensions.Unwrap()来支持“冷任务”?

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2013-08-13 09:19:26

您所需要做的就是在展开Task之前保留它并启动它:

代码语言:javascript
复制
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;
}

用法:

代码语言:javascript
复制
cache.GetOrAddAsync(
    "key", async () =>
    {
        var r = await AsyncOperation();
        return r.FastSynchronousTransform();
    });
票数 6
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/18201247

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档