冷任务和TaskExtensions.Unwrap [英] Cold Tasks and TaskExtensions.Unwrap

查看:373
本文介绍了冷任务和TaskExtensions.Unwrap的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用冷(未开始)任务,以避免多次运行这么贵的东西缓存类。

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的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆