How to wait until await / async methods finish
async-await, c#, multithreading, task-parallel-library
Solution
I answered the original(?) question on how to handle the finish of `ProcessSearchAsync` itself here.
To run tasks in parallel (as asked in the comments), here's your code modified, it gets a little complicated because of `invoiceTypes == null` and `_invoiceAccounts == null` checks. Note the way the checks are implemented below slightly changes the logic (previously it did WCF calls only if both _invoiceTypes and _invoiceAccounts were null - what if only one of them is null?):
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();
}
Problem
I have the following Async method: ``` 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(); } } ``` I don't want to execute SetupInvoiceGrid until _invoiceTypes, _invoiceAccounts and _ds have finished. Any clue? Am I doing it right? Should I be using Task instead of await? I have come up with this code that seems is working and looks fine to me but don't really know if its correct: ``` 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(); } ```