In a Form, in the Load event I need to kick off two tasks (as below). And then have it call my form object when either completes. How can I do that?
Or, am I not understanding this right? I did set my load method to be async. So does that mean it returned from the call to Load immediately, but did not complete as I called LoadMetadata with an await? And therefore the Form all processed right, but Load won't execute all code until one of the tasks completes.
Is that it? And so I'm ok. (I may be so used to all the housekeeping I have to do around threads, I'm making this more complicated than it is.)
private async void LoadingMetadata_Load(object sender, EventArgs e)
{
// load the metadata - this creates a task and returns.
var result = await LoadMetadata(this, profile, source.Token);
}
private static async Task<bool> LoadMetadata(LoadingMetadata dlg, DataSourceProfile profile, CancellationToken cancellationToken)
{
// We create a TaskCompletionSource of decimal
var taskCompletionSource = new TaskCompletionSource<bool>();
// Registering a lambda into the cancellationToken
cancellationToken.Register(() =>
{
// We received a cancellation message, cancel the TaskCompletionSource.Task
taskCompletionSource.TrySetCanceled();
});
// load the metadata
Task<bool> task = Task.Run(() => { profile.ReloadMetadata(); return true; } );
// Wait for the first task to finish among the two
var completedTask = await Task.WhenAny(task, taskCompletionSource.Task);
// If the completed task is our long running operation we set its result.
if (completedTask == task)
{
// Extract the result, the task is finished and the await will return immediately
var result = await task;
// Set the taskCompletionSource result
taskCompletionSource.TrySetResult(result);
}
// close the dialog
bool success = await taskCompletionSource.Task;
dlg.DialogResult = success ? DialogResult.OK : DialogResult.Cancel;
dlg.Close();
// Return the result of the TaskCompletionSource.Task
return success;
}