|If you have a large or unknown number of tasks, or you don't care about the value (if any) returned by the tasks, then
Task.WhenAll is usually the simplest option. But it's not required to get multiple tasks running at the same time.
If you're just loading data and setting the properties on your view-models, you generally don't need to be running on the UI thread. If you're updating a collection, you might need to use BindingOperations.EnableCollectionSynchronization[^] to enable updates from a background thread; but most property changes on a view-model will just work from any thread.
But as you discovered, you will need to be running on the UI thread to show another view. Therefore, you probably want to split the job into multiple tasks: a top-level task which kicks off the loading tasks, awaits
Task.WhenAll to wait for them to finish (without using
ConfigureAwait), and then displays the dialog; and multiple sub-tasks which load the data and update the view-model, which can use
private async Task LoadProjects(VendorsByProjectAndJobReportViewModel vm)
var projects = await Task.Run(() => AppCore.BizObject.GetProjectHeaders(AppCore.AppCompany.Id).ToList()).ConfigureAwait(false);
vm.Projects = projects;
private async Task LoadJobs(VendorsByProjectAndJobReportViewModel vm)
var jobs = await Task.Run(() => AppCore.BizObject.GetJobListHeaders(AppCore.AppCompany.Id).ToList()).ConfigureAwait(false);
vm.Jobs = jobs;
private async Task ShowVendorsByProjectAndJobReport()
WaitIndicatorVisibility = Visibility.Visible;
var dialogVm = new VendorsByProjectAndJobReportViewModel();
var tasks = new List<Task>
DialogResultEx result = DialogService.ShowDialog(dialogVm, typeof(MainWindowView));
"These people looked deep within my soul and assigned me a number based on the order in which I joined."