Search code examples
c#asp.netwcfcaching

Caching WCF service and Convert data as Async


We are trying to cache the data of a WCF service, So when the data is available in cache memory we need to return cached data from the cache as AsyncResult because the data is an object type and the Start method is IAsyncResult.

Here I can't change the return type because its an abstract member in the helper class.

As well as I cant check from the parent page caching available and pass because this needs to be changed globally so those who are consuming this service can make use of it.

public override IAsyncResult Start(object sender, EventArgs e, AsyncCallback cb, object extraData)
  {
   if(cache.Get("key")
     {
      //Needs to return the result Async format which is there as object in cache.
     }
  svc = new service.GetData(m_url);
  if (m_debug_mode) // not thread safe
    {
      return ((service.GetData)svc).BeginCallDataDebug(request, cb, extraData);
    }
   return ((service.GetData)svc).BeginCallData(request, cb, extraData);
   }

public override void End(IAsyncResult ar)
  {
    try
      {
        data = ((service.GetData)m_svc).EndCallData(ar);
        if(data !=null)
        cache.Add("key", data, null, absoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
      }

   catch(Exception ex)
    {
     Log(ex.message);
    }
  }

Solution

  • System.Threading.Tasks.Task implements IAsyncResult.

    If the data is found in the cache, you can return a completed Task with the result via Task.FromResult. Otherwise, you make the call to the service.

    public override IAsyncResult Start(object sender, EventArgs e, AsyncCallback cb, object extraData)
    {
        Object cachedData = cache.Get("key");
        if (cachedData != null)
        {
            // Return cached data.
            return Task.FromResult<object>(cachedData);
        }
    
        // Make call to the service.
        svc = new service.GetData(m_url);
        if (m_debug_mode) // not thread safe
        {
            return ((service.GetData)svc).BeginCallDataDebug(request, cb, extraData);
        }
        return ((service.GetData)svc).BeginCallData(request, cb, extraData);
    }
    

    In the End method, you can check the IAsyncResult type to access the result value.
    (Or you set a state flag/field in the Start method about whether your called the service or not; you could check the service svc field which will be null when cached data is being used.)

    public override void End(IAsyncResult ar)
    {
        try
        {
            Task<object> task = ar as Task<object>;
            if (task != null)
            {
                data = task.Result;
            }
            else
            {   
                data = ((service.GetData)m_svc).EndCallData(ar);
                if(data !=null)
                    cache.Add("key", data, null, absoluteExpiration, Cache.NoSlidingExpiration, CacheItemPriority.Default, null);
                }
            }
        }
        catch(Exception ex)
        {
            Log(ex.message);
        }
    }