Why does this async lambda function invocation not compile in C#?

别来无恙 提交于 2019-12-23 23:24:11

问题


I seem to be missing something really basic in my understanding. I am trying to call an async function that will take a Func<T> passed in by the caller, in case if the async function doesn't find a value in the cache. I am really puzzled as to why my code won't compile.

My calling code is as follows

static void Main(string[] args)
{
    Func<Task<string>> dataFetcher = async () =>
    {
        string myCacheValue = await new HttpClient().GetStringAsync("http://stackoverflow.com/");
        return myCacheValue;
    };

    MyCache<string> cache = new MyCache<string>();

    string mValue = cache.GetOrCreateAsync("myCacheKey", dataFetcher).Result;

}

MyCache is as follows

internal class MyCache<T> where T: class
{
    private Cache localCache = null;

    public MyCache()
    {
        localCache = new Cache();
    }
    public T GetOrCreate(string cacheKey, Func<T> doWork)
    {
        T cachedObject = null;
        if (string.IsNullOrEmpty(cacheKey) || string.IsNullOrWhiteSpace(cacheKey))
            return cachedObject;

        cachedObject = localCache.Get(cacheKey) as T;

        if (null == cachedObject)
        {
            cachedObject = doWork();
        }

        localCache.Add(cacheKey, cachedObject, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);

        return cachedObject;
    }

    public async Task<T> GetOrCreateAsync(string cacheKey, Func<T> doWork)
    {
        T cachedObject = null;

        if (string.IsNullOrEmpty(cacheKey) || string.IsNullOrWhiteSpace(cacheKey))
            return cachedObject;

        try
        {
            cachedObject = await Task.Factory.StartNew<T>(doWork);
            localCache.Add(cacheKey, cachedObject, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
        }
        catch (Exception)
        {
            cachedObject = null;
        }
        finally
        {
        }

        return cachedObject;
    }
}

In the calling code the line

string mValue = cache.GetOrCreateAsync("myCacheKey", dataFetcher).Result;

gives me a compile time error Argument 2: cannot convert from System.Func<System.Threading.Tasks.Task<string>> to System.Func<string>

I am at a loss as to what am I missing out on? If someone could help that will be great!

Thanks ~KD


回答1:


Use an overloaded method and pass a Func<Task<T>> argument to it. Then you can await on that result (which is a Task<T>).

public async Task<T> GetOrCreateAsync(string cacheKey, Func<Task<T>> doWorkAsync)
{
    T cachedObject = null;

    if (string.IsNullOrEmpty(cacheKey) || string.IsNullOrWhiteSpace(cacheKey))
        return cachedObject;

    try
    {
        cachedObject = await doWorkAsync();
        localCache.Add(cacheKey, cachedObject, null, DateTime.Now.AddMinutes(5), Cache.NoSlidingExpiration, CacheItemPriority.Normal, null);
    }
    catch (Exception)
    {
        cachedObject = null;
    }
    finally
    {
    }

    return cachedObject;
}


来源:https://stackoverflow.com/questions/40558237/why-does-this-async-lambda-function-invocation-not-compile-in-c

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!