嵌套任务的C#代码运行速度比相同代码慢,而顶层只有Tasks

时间:2017-10-05 18:58:26

标签: c# multithreading performance asynchronous async-await

我遇到了一个问题,即场景1的运行速度比场景2慢,即使场景1似乎应该运行得更快,因为它不仅在更高级别打开任务,而且在内部级别打开。有点像父子概念(我知道父/子实际上并没有发生,因为我认为任务都在同一级别运行)。场景2只是在更高级别创建任务,并且整体运行得更快。我唯一能想到的是,运行较少的任务会更快,因此可以并行处理所有内容,而不是尝试打开更多可能导致等待4核(8线程)CPU的任务。

我试图弄清楚场景2是否总是会更快,或者是否有更好的方法来编码场景1,以便它实际上比场景2更快。

场景1(嵌套任务):

public void MainFunction() {
    IList<Task<ProductMaster>> tasks = new List<Task<ProductMaster>>();
    foreach (var x in products) 
    {
        Task<ProductMaster> prodMaster = Task.Factory.StartNew<ProductMaster>(() => RunProductMasterCode(param1, param2));

        tasks.Add(prodMaster);   
    }

    foreach (Task<ProductMaster> tsk in tasks)
    {
        ProductMaster prodMaster = tsk.Result;
        // COMPLEX CODE HERE THAT RELIES ON tsk.Result
    }
}

public ProductMaster RunProductMasterCode(int param1, int param2) {
    IList<Task<ProductSub>> tasks = new List<Task<ProductSub>>();
    foreach (var x in subProducts) 
    {
        Task<ProductSub> prodSub = Task.Factory.StartNew<ProductSub>(() => RunProductSubCode(param1));

        tasks.Add(prodSub);
    }

    foreach (Task<ProductSub> tsk in tasks)
    {
        ProductSub prodSub = tsk.Result;
        // COMPLEX CODE HERE THAT RELIES ON tsk.Result
    }
}

public ProductSub RunProductSubCode(int param1) {
    // COMPLEX CODE HERE
}

场景2(单层任务通知我没有在RunProductMasterCode()中创建任务):

public void MainFunction() {
    IList<Task<ProductMaster>> tasks = new List<Task<ProductMaster>>();
    foreach (var x in products) 
    {
        Task<ProductMaster> prodMaster = Task.Factory.StartNew<ProductMaster>(() => RunProductMasterCode(param1, param2));

        tasks.Add(prodMaster);   
    }

    foreach (Task<ProductMaster> tsk in tasks)
    {
        ProductMaster prodMaster = tsk.Result;
        // COMPLEX CODE HERE THAT RELIES ON tsk.Result
    }
}

public ProductMaster RunProductMasterCode(int param1, int param2) {
    foreach (var x in subProducts) 
    {
        // NO THREADING HERE
        var prodSub = RunProductSubCode(param1);
    }
}

public ProductSub RunProductSubCode(int param1) {
    // COMPLEX CODE HERE
}

1 个答案:

答案 0 :(得分:5)

创建一个StartNew的任务只是为了立即等待结果,在添加构造任务的开销,调度线程池上的工作,等待调度该线程池线程,以及然后等待工作完成后再次安排原始线程。

让原始线程同步执行实际工作具有与构建该任务相同的所有好处,然后您可以立即等待,而无需任何额外的(相当昂贵的)开销。

如果您的所有代码实际上都需要完全同步运行,那么您根本不应该使用任何任务,只需运行代码即可。