多任务继续-等待所有任务完成

时间:2018-11-01 18:11:40

标签: c# task-parallel-library

我有以下代码,首先运行查询并添加原始结果ViewModel.RawContracts.AddRange(contractResults);

然后,我想用多个不同的数据源(例如, _enrichmentHelper.ResolveSecurities(token, contractsToEnrich);这些方法中的所有扩展本身都是异步完成的。

所有这些扩充操作完成之后,我想运行最后一段代码,以获取现在已扩充的原始数据,将其添加到我的网格ViewModel.ContractRows.AddRange(ViewModel.RawContracts);

但是,一旦查询任务完成,而不是在每个充实连续完成之后,我的最终延续queryAndEnrichmentTask就会执行。

我在这里做错了什么?

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();

1 个答案:

答案 0 :(得分:1)

您在外部任务中创建queryTask,但是从不等待它。外部任务将在queryTask完成之前返回。外部任务返回时,外部任务上的ContinueWith()将运行,并且不会等待queryTask完成。

最小的解决方法是等待queryTask结束包含它的任务块。外部任务仍将返回,但是其Task将被设置为未完成状态,从而允许ContinueWith()通过等待然后继续进行来完成其工作。

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