C# 提早異步加載數據

前言

在咱們應用程序中,若是有較大的數據須要從數據庫或者本地讀取,且是一次性的話,能夠提早獲取數據並緩存在內存中。html

通常處理方法:利用應用程序啓動到用戶使用功能這一段時間,提早加載數據。數據庫

問題來了,因數據大小的不固定性,提早加載的速度有快有慢,若是保證不會重複讀取數據庫、只返回一次結果呢?緩存

Task ConfigureAwait

使用ConfigureAwait能夠解決以上問題。詳情以下:安全

 程序啓動後,在相應的事件中,調用初始化方法

 1     private Task<List<EnglishWordInfo>> _wordsCacheDelayTask;
 2     /// <summary>
 3     /// 提早初始化字典
 4     /// 注:經過InitWordInfos提早緩存數據,提高用戶體驗
 5     /// </summary>
 6     public void InitWordInfos()
 7     {
 8         if (_wordsCacheDelayTask == null)
 9         {
10             _wordsCacheDelayTask = GetWordsTask();
11         }
12     }

使用ConfigureAwait異步獲取數據

經過ConfigureAwait的使用,不等待結果的返回。異步

 1     /// <summary>
 2     /// 延時獲取數據
 3     /// 注:延時獲取,避免界面卡頓
 4     /// </summary>
 5     /// <returns></returns>
 6     private async Task<List<EnglishWordInfo>> GetWordsTask()
 7     {
 8         return await Task.Run(() =>
 9         {
10             return EnglishDictService.Instance.GetWords();
11         }).ConfigureAwait(false); 
12     }

添加封裝數據延遲任務

若是不是程序啓動後當即加載緩存,而是程序使用期間對數據緩存的處理。能夠添加以下對緩存延遲任務的封裝,保證只獲取一次緩存數據。async

 1     /// <summary>
 2     /// 獲取數據延遲任務
 3     /// 注:若是沒有提早延遲任務,則從新獲取數據
 4     /// </summary>
 5     public Task<List<EnglishWordInfo>> WordsCacheDelayTask
 6     {
 7         set => _wordsCacheDelayTask = value;
 8         get
 9         {
10             if (_wordsCacheDelayTask == null)
11             {
12                 _wordsCacheDelayTask = GetWordsTask();
13             }
14 
15             return _wordsCacheDelayTask;
16         }
17     }

獲取緩存數據

經過Task.Result,獲取緩存任務的結果,此緩存任務的狀態能夠是:post

  • 執行中 -- 則會在原有進度下,繼續執行並返回結果
  • 已完成 -- 則會返回原有的結果

不管獲取多少次,Result只會返回一樣的結果,能夠把WordsCacheDelayTask.Result當作是一個靜態的緩存。spa

1     /// <summary>
2     /// 獲取緩存數據
3     /// </summary>
4     private List<EnglishWordInfo> WordInfosCache => WordsCacheDelayTask.Result;

 

參考列表:code

在編寫異步方法時,使用 ConfigureAwait(false) 避免使用者死鎖htm

將 async/await 異步代碼轉換爲安全的不會死鎖的同步代碼(使用 PushFrame)

相關文章
相關標籤/搜索