2013-08-17 81 views
4

我有以下的異步方法:如何等到的await /異步方法完成

private async void ProcessSearch() 
{ 
    // get catalogs on first search 
    if (_invoiceTypes == null && _invoiceAccounts == null) 
    { 
     var confWcf = new Data.ConfigurationWCF(); 
     _invoiceTypes = await confWcf.GetInvoiceTypesAsync(MainForm.State.Entity); 
     _invoiceAccounts = await confWcf.GetInvoiceAccountsAsync(MainForm.State.Entity); 
     confWcf.Dispose(); 
    } 

    var seekWcf = new DataSeekWCF(); 
    _ds = await seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value)); 
    seekWcf.Dispose(); 

    if (_ds != null) 
    { 
     SetupInvoiceGrid(); 
    } 
} 

我不想執行SetupInvoiceGrid直到_invoiceTypes,_invoiceAccounts和_ds已經完成。

任何線索?我做對了嗎?我應該使用任務而不是等待?


我想出了這個代碼,似乎是工作,看起來好像沒什麼問題,但真的不知道,如果它的正確:

private void btnSearch_Click(object sender, EventArgs e) 
{ 
    lock (lockObj) 
    { 
     if (_isBusy) 
      return; 
     else 
      _isBusy = true; 
    } 

    ShowPleaseWait(Translate("Searching data. Please wait...")); 
     if (_invoiceTypes == null && _invoiceAccounts == null) 
     { 
      var t = GetCatalogs(); 
      t.ContinueWith(t2 => 
      { 
       if (t.IsCompleted) ProcessSearch(); 
      }); 
     } 
     else 
     { 
      ProcessSearch(); 
     } 
} 

private async Task GetCatalogs() 
{ 
    // get catalogs on first search 
    Data.ConfigurationWCF confWcf = new Data.ConfigurationWCF(); 
    var task1 = confWcf.GetInvoiceTypesAsync(1); 
    var task2 = confWcf.GetInvoiceAccountsAsync(1); 
    confWcf.Dispose(); 

    await Task.WhenAll(task1, task2); 

    _invoiceTypes = task1.Result; 
    _invoiceAccounts = task2.Result; 

    if (_invoiceTypes != null) 
    { 
     cboInvoiceType.DataSource = _invoiceTypes.Tables["invoice_types"]; 
     cboInvoiceType.DisplayMember = "description"; 
     cboInvoiceType.ValueMember = "code"; 
    } 

} 

private async void ProcessSearch() 
{ 
    var seekWcf = new Data.SeekWCF(); 
    _ds = await seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value)); 
    seekWcf.Dispose(); 

    if (_ds != null) 
    { 
     SetupInvoiceGrid(); 
    } 
    HidePleaseWait(); 
} 
+0

您是否嘗試過運行此操作以查看它是否有效?我看起來很好。 –

+1

這工作..但我想例如並行運行GetInvoiceTypesAsync和GetInvoiceAccountsAsync與SearchInvoiceAdminAsync。所以3個飛蛾運行pararell,但我不能執行SetupInvoiceGrid,直到所有這些完成。 – VAAA

回答

3

我回答關於如何原來的問號(?)處理ProcessSearchAsync本身here的完成。

要並行運行任務(如註釋中所述),這裏是您的代碼修改,由於invoiceTypes == null_invoiceAccounts == null檢查,它會變得有點複雜。注意檢查以下實現方式略有改變邏輯(之前它並WCF調用僅當_invoiceTypes和_invoiceAccounts都爲空的 - 如果只有其中一個爲空):

private async Task ProcessSearchAsync() 
{ 

    Data.ConfigurationWCF confWcf = new Data.ConfigurationWCF(); 
    Task</*typeof _invoiceTypes*/> t1; 
    Task</*typeof _invoiceAccounts*/> t2; 

    if (_invoiceTypes == null) 
     t1 = confWcf.GetInvoiceTypesAsync(MainForm.State.Entity); 
    else 
    { 
     var tsc1 = new TaskCompletionSource</*typeof _invoiceTypes*/>(); 
     t1 = tsc1.Task; 
     tsc1.SetResult(_invoiceTypes); 
    } 

    if (_invoiceAccounts == null) 
     t2 = confWcf.GetInvoiceAccountsAsync(MainForm.State.Entity); 
    else 
    { 
     var tsc2 = new TaskCompletionSource</*typeof _invoiceAccounts*/>(); 
     t2 = tsc2.Task; 
     tsc2.SetResult(_invoiceAccounts); 
    } 


    DataSeekWCF seekWcf = new DataSeekWCF(); 
    Task</*typeof _ds*/> t3 = seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value)); 

    await Task.WhenAll(new Task[] {t1, t2, t3}); 
    _invoiceTypes = t1.Result; 
    _invoiceAccounts = t2.Result; 
    ds = t3.Result; 

    if (_ds != null) 
    { 
     SetupInvoiceGrid(); 
    } 

    confWcf.Dispose(); 
    seekWcf.Dispose(); 
} 
+1

我想要例如與SearchInvoiceAdminAsync並行運行GetInvoiceTypesAsync和GetInvoiceAccountsAsync。所以3個飛蛾運行pararell,但我不能執行SetupInvoiceGrid,直到所有這些完成。 – VAAA

+0

ProcessSearchAsync與我有同樣的方法,但返回Task而不是void? – VAAA

+0

不,'ProcessSearchAsync'就是你在聲明'async'時應該如何命名的。我將展示如何在答案中並行運行任務。 – avo

0

到你的微小變化到了那裏會做你想做的。你可以開始新的任務,然後做其他的事情,然後在你繼續之前等待。正如@Noseratio有幫助地指出的那樣,下面的代碼片段不是生產就緒的,因爲我沒有檢查錯誤條件(如null引用等)。關鍵是你可以簡單而優雅地並行執行這些事情,而不必訴諸於使用非常多的任務API。我值得指出的一個調整是,您想要將呼叫轉移到Dispose進入延續(即,在所有await之後),因爲如果您在調用* Async方法後立即嘗試呼叫Dispose,那麼您很有可能會失敗你的WCF客戶端獲得響應的一半,awaits可能會引發拋出異常(我不感興趣)。

private async void ProcessSearchAsync() 
{ 

    Data.ConfigurationWCF confWcf = new Data.ConfigurationWCF(); 
    Task</*typeof _invoiceTypes*/> t1; 
    Task</*typeof _invoiceAccounts*/> t2; 

    // get catalogs on first search 
    if (_invoiceTypes == null && _invoiceAccounts == null) 
    { 
     t1 = confWcf.GetInvoiceTypesAsync(MainForm.State.Entity); 
     t2 = confWcf.GetInvoiceAccountsAsync(MainForm.State.Entity); 
    } 

    DataSeekWCF seekWcf = new DataSeekWCF(); 
    Task</*typeof _ds*/> t3 = seekWcf.SearchInvoiceAdminAsync(new Guid(cboEmployer.Value.ToString()), new Guid(cboGroup.Value.ToString()), txtSearchInvoiceNumber.Text, chkSearchLike.Checked, txtSearchFolio.Text, Convert.ToInt32(txtYear.Value)); 

    _invoiceTypes = await t1; 
    _invoiceAccounts = await t2; 
    _ds = await t3; 

    if (_ds != null) 
    { 
     SetupInvoiceGrid(); 
    } 

    confWcf.Dispose(); 
    seekWcf.Dispose(); 
} 
+0

你認爲我剛剛編輯的問題的更新代碼是好的嗎?非常感謝 – VAAA

+0

是的,我認爲你的更新看起來基本正確。我認爲使用'Task.WhenAll'可以讓你的語法更加冗長,但它應該沒問題。 –

+0

不錯!我想Im學習任務等待/異步的東西:) – VAAA