简体   繁体   中英

Multiple Task Continuation - wait until all complete

I have the following piece of code whereby I first run a query and add the raw results ViewModel.RawContracts.AddRange(contractResults);

I then want to enrich this set of data with multiple different data sources eg _enrichmentHelper.ResolveSecurities(token, contractsToEnrich); all of the enrichment within these methods are themselves done asynchronously.

Once all this enrichment has been completed I want to run a final piece of code to take the now enriched raw data to add it to my grid ViewModel.ContractRows.AddRange(ViewModel.RawContracts);

However my final Continuation queryAndEnrichmentTask is executing once the query task completes rather than after each of the enrichment continuations complete.

What am I doing wrong here?

Task.Factory.StartNew
(
    () =>
    {
        Log.Debug("Starting getting contracts");
        Task queryTask = _serviceModel.GetContractsByCriteriaAsync(token, ViewModel.QueryRequest)
            .LogExceptions()
            .ContinueWith
            (
                prevTask =>
                {
                    if (!token.IsCancellationRequested)
                    {
                        IQueryResponse response = null;
                        Log.Debug("Received contract response.");

                        if (prevTask.IsFaulted || (response = prevTask.Result) == null)
                        {
                            ViewModel.ErrorMessage = "Failed to load contracts. Please check the log file for details.";
                        }
                        else
                        {
                            if (response.Contracts != null)
                            {
                                Log.Debug($"Start loading {response.Contracts.Count()} contract positions...");

                                bool successful = true; 

                                if (successful && prevTask.IsCompleted && prevTask.Result != null)
                                {
                                    contractResults = prevTask.Result.Contracts.ToList();
                                    ViewModel.RawContracts.Clear();
                                    ViewModel.RawContracts.AddRange(contractResults);
                                }
                                Log.Debug("Finished loading contracts");
                            }
                        }
                    }
                    Log.Debug("Finished loading contracts");

                }, token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default
            ); // End add raw results task

            IList<IContract> contractsToEnrich = ViewModel.RawContracts;

            queryTask.ContinueWith(prevTask =>
            {
                _enrichmentHelper.ResolveSecurities(token, contractsToEnrich);
            }, token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);

            queryTask.ContinueWith(prevTask =>
            {
                _enrichmentHelper.ResolveBooks(token, contractsToEnrich);
            }, token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);

            queryTask.ContinueWith(prevTask =>
            {
                _enrichmentHelper.ResolveCounterparties(token, contractsToEnrich);
            }, token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);

            queryTask.ContinueWith(prevTask =>
            {
                _enrichmentHelper.ResolveLegalEntities(token, contractsToEnrich);
            }, token, TaskContinuationOptions.AttachedToParent | TaskContinuationOptions.OnlyOnRanToCompletion, TaskScheduler.Default);
    }, token
)
.LogExceptions()
.ContinueWith
(
    queryAndEnrichmentTask =>
    {
        Log.Debug("Post search task started");

        if (queryAndEnrichmentTask.IsFaulted)
        {
            if (!ViewModel.HasErrorMessage)
                ViewModel.ErrorMessage = "Error occured when loading data. Please refer to log file for details";
        }
        else
        {
            ViewModel.ContractRows.AddRange(ViewModel.RawContracts);
        }
        Log.Debug("Post search task completed");
    }, token, TaskContinuationOptions.NotOnCanceled, TaskScheduler.Default)
.LogExceptions();

You create queryTask inside an outer task, but never await it. The outer task will return before queryTask completes. The ContinueWith() on the outer task will run when the outer task returns, and won't wait for queryTask to complete.

The smallest fix is to await queryTask before ending the task block that contains it. The outer task will still return but its Task will be set to an incomplete state, allowing ContinueWith() to do its job by awaiting it and then proceeding.

    await queryTask;  //<-- add this
)
.LogExceptions()
.ContinueWith
(
    queryAndEnrichmentTask =>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM