2016-11-17 48 views
0

我必須同步數據從WCF Web服務未來在SQLite數據庫。 這種同步表示Web服務的一打,在4個類別可被「分組」:UWP:如何通過異步WCF Web服務和SQLite之間的優化同步調用

  • 用戶」版權
  • 形式」的數據,其可以從兩側被更新(用戶/服務器)
  • 服務器」數據,這些數據只能從服務器更新
  • 查看」數據,至極本地複製的意見服務器

每次調用WebService的是通過HttpClient的完成:

response = await client.PostAsync(webServiceName, content); 

每個web服務都有自己的異步方法其中WebService的響應反序列化

public static async Task<string> PushForm(List<KeyValuePair<string, string>> parameters) 
{ 
    var response = await JsonParser.GetJsonFromUrl(WebServiceName.PushForm.Value, parameters); 
    Forms forms = new Forms(); 
    try 
    { 
     forms = JsonConvert.DeserializeObject<Forms>(response); 
     return response; 
    } 
    catch (Exception e) 
    { 
     throw new Exception(e.Message); 
    } 
} 

然後我有一個SynchronizationS ervice類,在這裏我按類別重新組合調用Web服務:

public async Task<bool> SynchronizeServerData() 
{ 
    bool result = false; 
    try 
    { 
     result = true; 
     List<Table1> tables1 = await WebServices.GetListTable1(null); 
     if (tables1 != null) 
     { 
      ServiceLocator.Current.GetInstance<IRepository>().DeleteAll<Table1>(true); 
      ServiceLocator.Current.GetInstance<IRepository>().AddAll<Table1>(tables1); 
     } 
     List<Table2> tables2 = await WebServices.GetListTable2(null); 
     if (tables2 != null) 
     { 
      ServiceLocator.Current.GetInstance<IRepository>().DeleteAll<Table2>(true); 
      ServiceLocator.Current.GetInstance<IRepository>().AddAll<Table2>(tables2); 
     } 
     List<Table3> tables3 = await WebServices.GetListTable3(null); 
     if (tables3 != null) 
     { 
      ServiceLocator.Current.GetInstance<IRepository>().DeleteAll<Table3>(true); 
      ServiceLocator.Current.GetInstance<IRepository>().AddAll<Table3>(tables3); 
     } 
     ... 
    } 
    catch (Exception e) 
    { 
     result = false; 
    } 
    return result; 
} 

最後,在主視圖模型,我把每一種方法:

public async void SynchronizeData(bool firstSync) 
{ 
    IsBusy = true; 
    var resUsers = await _synchronisation.SynchronizeUsersRights(); 
    var resServer = await _synchronisation.SynchronizeServerData(); 
    var resForm = await _synchronisation.SynchronizeForms(); 
    var resViews = await _synchronisation.SynchronizeViews(); 
    IsBusy = false; 
} 

但由於使用「等待」的表現並不好。

=>我想知道是否有一種簡單的方法來「優化性能」並行化調用?或者是否可以將數據恢復從SQLite更新中分離出來?

回答

1

在它的面前,似乎有同時運行的幾件事情的機會,例如在SynchronizeData你可以這樣做,而不是:

{ 
    IsBusy = true; 
    Task resUsersTask = _synchronisation.SynchronizeUsersRights(); 
    Task resServerTask = _synchronisation.SynchronizeServerData(); 
    Task resFormTask = _synchronisation.SynchronizeForms(); 
    Task resViewsTask = _synchronisation.SynchronizeViews(); 
    await Task.WhenAll(resUsersTask, resServerTask, resFormTask, resViewsTask); 
    var resUsers = resUsersTask.Result; 
    var resServer = resServerTask.Result; 
    var resForm = resFormsTask.Result; 
    var resViews = resViewsTask.Result;  
    IsBusy = false; 
} 

...這將讓那些4個任務同時運行。

你可以在SynchronizeServerData;例如:

result = true; 
Task tables1Task = WebServices.GetListTable1(null); 
Task tables2Task = WebServices.GetListTable2(null); 
Task tables3Task = WebServices.GetListTable3(null); 

List<Table1> tables1 = await tables1Task; 
// ... 

List<Table2> tables2 = await tables2Task; 
// ... 

List<Table3> tables3 = await tables3Task; 
// ... 

這將允許3個任務同時運行。

您從中獲得多少實際收益取決於SQLite是否允許您執行多個併發請求 - 我不知道這個問題的答案。

一些其他意見:

public async void SynchronizeData(bool firstSync) 

async void幾乎總是不正確的,除了事件處理程序和罕見的發射後不管的方法,通常是async Task你想要什麼。搜索任何數量的好答案爲什麼。

最後,你真正應該做的是配置代碼,看看你真正的瓶頸在哪裏。

+0

感謝您的反饋。 但有沒有辦法通過Task.WhenAll()知道異步任務調用的「結果」? 我需要知道這個結果,並在同步失敗時通知用戶。 –

+0

是的;請參閱[Task.WhenAll]上的文檔(https://msdn.microsoft.com/en-us/library/hh194874(v = vs.110).aspx)。如果您願意,也可以先創建任務(正如我在SynchronizeServerData示例中所示),然後檢查每個結果(例如, with Task.Result,WhenAll()完成後。 – sellotape

+0

順便說一句,因爲我有點省略了最初的結果檢索,我已經調整了答案以反映一種方式來做到這一點。如果你有很多任務,你可能會使用一個集合,但只有4個,這很容易,就這樣。 – sellotape