问题
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