最后,当所有+继续

时间:2015-06-13 00:29:02

标签: c# task-parallel-library

我想要同时运行三个顶级进程。在完成两个进程之后,我有需要运行的子进程,一个需要同时运行的集合。我面临的唯一问题是Flush in最终在子进程完成之前执行。我已经插入了一些跟踪语句,结果就是这样:

Pulling AssetList
Pulling MarketImports
Pulling AccountBalance
AccountBalance Pulled
MarketImports Pulled
Pulling WalletTransactions
AssetList Pulled
Pulling BlueprintList
Pulling MarketOrders
Pulling IndustryJobs
Flushing
MarketOrders Pulled
BlueprintList Pulled
IndustryJobs Pulled
WalletTransactions Pulled

如何在子流程完成后进行Flush?有问题的代码如下:

private async Task DoPull(string token, string name, Func<string, Task> func)
{
    Trace.WriteLine(string.Format("Pulling {0}", name));
    await func(token);
    StopSteps(token, name);
    Trace.WriteLine(string.Format("{0} Pulled", name));
}

try
{
    await Task.WhenAll(
        DoPull(tk, "AssetList", _assetMapper.Pull).ContinueWith(async c => await Task.WhenAll(
            DoPull(tk, "BlueprintList", _blueprintMapper.Pull), 
            DoPull(tk, "MarketOrders", _orderMapper.Pull), 
            DoPull(tk, "IndustryJobs", _jobMapper.Pull))),
        DoPull(tk, "MarketImports", _marketMapper.Pull).ContinueWith(async c => 
            await DoPull(tk, "WalletTransactions", _transactionMapper.Pull)),
        DoPull(tk, "AccountBalance", _balanceMapper.Pull));
}
catch (Exception)
{
    StopSteps(token, _running.ToArray());
}
finally { Flush(token); }

1 个答案:

答案 0 :(得分:0)

真实答案

在DoPull中,一旦等待的函数完成,执行将返回给调用者。这意味着,一旦所有其他人在其他DoPull调用中等待完成,它将继续在main方法中返回,然后点击finally块。在此之前无法保证StopStepsTrace.WriteLine调用将会执行。

不正确的东西

ContinueWith内的执行在任何地方都没有被等待。

您应该使用ContinueWith<Task>来获取该功能。

此外,有点难以跟随内联的所有内容,可能会稍微分解一下,以便更容易找出步骤是什么?

    private async Task Method()
    {
        try
        {
            var assetList = DoPull(tk, "AssetList", _assetMapper.Pull)
                .ContinueWith<Task>(t => Task.WhenAll(
                    DoPull(tk, "BlueprintList", _blueprintMapper.Pull),
                    DoPull(tk, "MarketOrders", _orderMapper.Pull),
                    DoPull(tk, "IndustryJobs", _jobMapper.Pull));

            var marketImport = DoPull(tk, "MarketImports", _marketMapper.Pull)
                .ContinueWith<Task>(t => DoPull(tk, "WalletTransactions", _transactionMapper.Pull));

            var accountBalance = DoPull(tk, "AccountBalance", _balanceMapper.Pull);

            await Task.WhenAll(assetList, marketImport, accountBalance);
        }
        catch (Exception)
        {
            StopSteps(token, _running.ToArray());
        }
        finally { Flush(token); }
    }

修改

    private async Task PullAssetList()
    {
        await DoPull(tk, "AssetList", _assetMapper.Pull);

        await Task.WhenAll(
                    DoPull(tk, "BlueprintList", _blueprintMapper.Pull),
                    DoPull(tk, "MarketOrders", _orderMapper.Pull),
                    DoPull(tk, "IndustryJobs", _jobMapper.Pull));
    }

    private async Task PullMarketImport()
    {
        await DoPull(tk, "MarketImports", _marketMapper.Pull);

        await DoPull(tk, "WalletTransactions", _transactionMapper.Pull);
    }

    private async Task PullAccountBalance()
    {
        await DoPull(tk, "AccountBalance", _balanceMapper.Pull);
    }

    private async Task Method()
    {
        try
        {
            await Task.WhenAll(PullAssetList(), PullMarketImport(), PullAccountBalance());
        }
        catch (Exception)
        {
            StopSteps(token, _running.ToArray());
        }
        finally { Flush(token); }
    }