mtkachenko mtkachenko - 1 month ago 10
ASP.NET (C#) Question

ASP.NET: cache task and call its result in synchronous code

I have synchronous HttpHandler. I want to cache result of HttpClient.GetAsync and use it in my HttpHandler. I did it this way:

public static class CacheFacade
{
private static Cache Cache => HttpRuntime.Cache;
private const string CacheKey = "asynccache";

public static string GetStringFromCache()
{
if (Cache[CacheKey] == null)
{
InitCache();
//fallback here; I can use data from some synchronous source
return "init cache" + " - " + Thread.CurrentThread.ManagedThreadId;
}
var task = (Task<string>) Cache[CacheKey];

if (!task.IsCompleted)
{
//and fallback here too
return task.Status + " - " + DateTime.UtcNow + " - " + Thread.CurrentThread.ManagedThreadId;
}

return task.Result;
}

private static void InitCache()
{
var task = Task.Run(GetDataAsync);
Cache.Insert(CacheKey, task, null, DateTime.Now.Add(TimeSpan.FromSeconds(10)),
Cache.NoSlidingExpiration);
}

private static async Task<string> GetDataAsync()
{
using (var httpClient = new HttpClient())
{
await Task.Delay(TimeSpan.FromSeconds(2));
var res = await httpClient.GetAsync("http://www.google.com");
return res.StatusCode + " - " + DateTime.UtcNow + " - " + Thread.CurrentThread.ManagedThreadId;
}
}
}


It works. Does this approach have any disadvantages?

usr usr
Answer

This is OK.

Note, that these cache items can only be stored in-process. You can't use an out-of-process cache because tasks cannot be serialized. You might or might not care about that.

In your fallback here; I can use data from some synchronous source handling you can also block on the task (or await it if architecturally possible).

HTTP handlers support async processing using tasks as well. I believe you need a tiny helper/wrapper for that which is easy to write or available on the web.

Comments