2013-11-29 2 views
0

фона:ASP.NET MVC3 как ждать асинхронным обратного вызова и возврата результата

Я работаю на функциональность кэша прогрева, чтобы увеличить производительность на ASP.NET MVC Web путем предварительной загрузки объекта в Кэш до его запроса.

Я использую кеш-ключ Azure In-Role, который предоставил функцию AddItemLevelCallback при обновлении/удалении/добавлении кеша и т. Д. Я поделился логикой кода ниже.

Проблема:

AddItemLevelCallback на NotifyOnceCacheIsUpdated показано на фрагменте кода ниже не становится вызывается сразу, пока не будет добавлен Пункт/обновляется. Запрос нужно будет ждать. Но проблема заключается в том, что AddItemLevelCallback isync и KickOffWarmUpCache в DAL может вернуться до добавления/обновления фактического элемента.

Каким будет элегантный способ справиться с этим сценарием, когда KickOffWarmUpCache возвращает результат только вызывающему абоненту только после запуска AddItemLevelCallback.

Технология: MVC3, .NET Framework 4.5

Пример кода:

CONTROLLER

public void WarmUpCache(string id) 
{ 
    var userInfo = BLL.KickOffWarmUpCache(string id); 
} 

BLL

public UserInfo KickOffWarmUpCache(string id) 
{ 
    return DAL.KickOffWarmUpCache(string id) 
} 

DAL

public UserInfo KickOffWarmUpCache(string id) 
{ 
    UserInfo userInfo = new UserInfo(); 
    //If Status = Progress 
    if (cache.Get(id).Status == "Progress") 
    { 
     NotifyOnceCacheIsUpdated(id,(result)=> 
     { 
      userInfo=result.userInfo; 
     }); 
    }else{ 
      userInfo=Cache.Get(id); 
    } 

     //This needs to wait for until callback is triggered and userInfo is populated 
     return userInfo; 
} 

UTIL

public void NotifyOnceCacheIsUpdated(string cacheKey, Action<T> callback) 
{ 
    DataCacheOperations allCacheOperations = DataCacheOperations.ReplaceItem | DataCacheOperations.AddItem ; 
    _ndItemLvlAllOps = cache.AddItemLevelCallback(cacheKey, allCacheOperations, 
        (CacheName, cacheRegion, cacheKey, itemVersion, OperationId, nd) => 
         { 
          cachedData = cache.Get(cacheKey); 
          callback(cachedData); 
         }); 
     } 
+0

Рассматривали вы просто с помощью '' Task' async'? – Aron

+0

Да, но не решит данную проблему I.e. результат ожидания и возврата, заданный функцией обратного вызова –

+1

... Результат ожидания и возврата - это ОТРАЖЕННАЯ ИДЕЯ '' '' '' '' async'. Или ваша проблема в том, что ваша текущая функция не включена в дружественную подпись TPL? Если это так, вы должны завершить логику в 'TaskCompletionSource'. – Aron

ответ

1
public Task<UserInfo> KickOffWarmUpCache(string id) 
{ 

    //If Status = Progress 
    if (cache.Get(id).Status == "Progress") 
    { 
     var ret = new TaskCompletionSource<UserInfo>(); 
     NotifyOnceCacheIsUpdated(id,(result)=> 
     { 
      //complete the task. 
      ret.SetResult(result.userInfo); 
     }); 
     //return a Task...which the SetResult will complete. 
     return ret.Task; 
    } 

    //Return a result synchronously 
    return Task.FromResult(Cache.Get(id)); 
} 
+0

Спасибо @aron, вы можете уточнить, что такое diff между ret ret.Task и Task.FromResult (new UserInfo()). Позднее возвращает нулевой объект? –

+0

Также я добавил else {userInfo = cache.Get (id);}. –

+0

'Task.FromResult' полезен для возврата задачи с уже завершенным результатом. Обычно вы используете его, когда можете синхронно генерировать результат. Пока 'TaskCompletionSource.Task' возвращает' Task', который еще не завершен, и может быть выполнен с помощью 'TaskCompletionSource.SetResult' другим потоком. – Aron

 Смежные вопросы

  • Нет связанных вопросов^_^