本文介绍了Cold Tasks 和 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 的 await,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() 通过将 Task> 转换为 Task 来完成我所需要的.,但它返回的包装器似乎实际上并不支持 Start() - 它会引发异常.

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() 替代方案?

Is there an alternative to TaskExtensions.Unwrap() that supports "cold tasks"?

推荐答案

你需要做的就是在展开它之前保留 Task 并开始它:

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();
    });

这篇关于Cold Tasks 和 TaskExtensions.Unwrap的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

10-29 03:59