C# 半并行运行多个任务

C# 半并行运行多个任务,c#,multithreading,async-await,task,C#,Multithreading,Async Await,Task,我有一个任务列表,其中每个任务有两个子任务。我只想在上一个任务完成第一个子任务后开始下一个任务。(第一个子任务对单个http api调用了大约1000次,如果我将其称为“太多”,则它似乎会关闭/限制,第二个任务是一个运行时间相当长的cpu受限任务) 我的想法与下面的示例代码类似(在实际情况中,任务列表增加到至少300个): 类程序 { 静态异步任务主(字符串[]args) { var test=新的TestMultiTask(); 等待测试。TestListOfTasks(); 控制台。写入线(

我有一个任务列表,其中每个任务有两个子任务。我只想在上一个任务完成第一个子任务后开始下一个任务。(第一个子任务对单个http api调用了大约1000次,如果我将其称为“太多”,则它似乎会关闭/限制,第二个任务是一个运行时间相当长的cpu受限任务)

我的想法与下面的示例代码类似(在实际情况中,任务列表增加到至少300个):

类程序
{
静态异步任务主(字符串[]args)
{
var test=新的TestMultiTask();
等待测试。TestListOfTasks();
控制台。写入线(“完成”);
Console.ReadLine();
}
} 
公共类测试多任务
{
公共列表任务{get;private set;}
公共异步任务TestListOfTasks()
{
任务=新列表();
Tasks.Add(Task2SubTask(newprogress(ReportProgress),0));
等待任务。何时(任务);
Console.WriteLine(“完成的测试列表任务”);
}
私有无效报告进度(MyProgress obj)
{
如果(目标进度编号<10)
{
Tasks.Add(Task2SubTask(新进度(ReportProgress),obj.ProgressNo+1));
}
}
专用异步任务Task2SubTask(IProgress progress,inti)
{
WriteLine($“Task{i},started.”);
wait Task.Delay(700);//模拟从web api获取数据(abt-1000调用)
WriteLine($“Task{i},completed subtask 1.”);
Report(new MyProgress(){Task1Done=true,ProgressNo=i});//现在下一个任务可以开始从web api获取数据了。
wait Task.Run(()=>Task.Delay(1000));//处理(在此任务中)从web api收集的数据
Console.WriteLine($“Task{i}done.”);//返回已处理的数据。
}
}
但是,这至少有一个缺陷-列表中的第一个任务完成后,
程序仍会继续运行,即使列表已展开。
有人知道更聪明的方法吗?(可能是完全不同的方法?)

编辑:
谢谢你的评论。。现在,我试图对代码进行注释,以使其更加清晰。

首先,感谢您的大量注释。我尝试了@Evk的建议,最终得到了以下代码

public class TestMultiTask2
{
    public List<Task> Tasks { get; private set; }
    public async Task TestListOfTasks()
    {
        var workers = new List<Worker>();
        var crunchingTasks = new List<Task>();
        var n = 10;
        for (int i = 0; i < n; i++)
        {
            var w = new Worker(i);
            workers.Add(w);
            await w.GetDataAsync(new Progress<MyProgress>(ReportProgress));
            crunchingTasks.Add(w.CrunchData(new Progress<MyProgress>(ReportProgress)));
        }
        await Task.WhenAll(crunchingTasks);
        Console.WriteLine($"Worker 0 data: {string.Join(", ", workers[0].Datas)}");
        Console.WriteLine($"Worker {n-1} data: {string.Join(", ", workers[n-1].Datas)}");
        Console.WriteLine("Finished TestListOfTasks");
    }

    private void ReportProgress(MyProgress obj)
    {
        if (obj.Task2Started)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has started chrunching data: {obj.Task2Started}");
        }
        else if(obj.Task2Done)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has finished chrunching data: {obj.Task2Done}");
        }
        else if (obj.Task1Done)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has finished getting data: {obj.Task1Done}"); 
        }
    }


}

public class MyProgress
{
    public int TaskNo { get; set; }
    public bool Task1Done { get; set; }
    public bool Task2Done { get; internal set; }
    public bool Task2Started { get; internal set; }
}

public class Worker
{
    public int ID { get; set; }

    public Worker(int id)
    {
        ID = id;
    }
    public List<int> Datas { get; set; } = new List<int>() { 0, 0, 0 };
    public async Task GetDataAsync(IProgress<MyProgress> progress)
    {
        await Task.Delay(500);
        Datas = new List<int>() { 1, 2, 3 };
        progress.Report(new MyProgress() { TaskNo = ID, Task1Done = true });
    }

    public async Task CrunchData(IProgress<MyProgress> progress)
    {
        progress.Report(new MyProgress() { TaskNo = ID, Task2Started = true });
        await Task.Run(async () => { await Task.Delay(5000); Datas.Reverse(); });
        progress.Report(new MyProgress() { TaskNo = ID, Task2Done = true });
    }
}
class Program
{


    static async Task Main(string[] args)
    {
        var test = new TestMultiTask2();
        await test.TestListOfTasks();
        Console.WriteLine("Finished");
        Console.ReadLine();
    }
}
公共类测试多任务2
{
公共列表任务{get;private set;}
公共异步任务TestListOfTasks()
{
var workers=新列表();
var crunchingTasks=新列表();
var n=10;
对于(int i=0;i{wait Task.Delay(5000);Datas.Reverse();});
Report(new MyProgress(){TaskNo=ID,Task2Done=true});
}
}
班级计划
{
静态异步任务主(字符串[]args)
{
var test=新的TestMultiTask2();
等待测试。TestListOfTasks();
控制台。写入线(“完成”);
Console.ReadLine();
}
}

首先,感谢您的评论。我尝试了@Evk的建议,最终得到了以下代码

public class TestMultiTask2
{
    public List<Task> Tasks { get; private set; }
    public async Task TestListOfTasks()
    {
        var workers = new List<Worker>();
        var crunchingTasks = new List<Task>();
        var n = 10;
        for (int i = 0; i < n; i++)
        {
            var w = new Worker(i);
            workers.Add(w);
            await w.GetDataAsync(new Progress<MyProgress>(ReportProgress));
            crunchingTasks.Add(w.CrunchData(new Progress<MyProgress>(ReportProgress)));
        }
        await Task.WhenAll(crunchingTasks);
        Console.WriteLine($"Worker 0 data: {string.Join(", ", workers[0].Datas)}");
        Console.WriteLine($"Worker {n-1} data: {string.Join(", ", workers[n-1].Datas)}");
        Console.WriteLine("Finished TestListOfTasks");
    }

    private void ReportProgress(MyProgress obj)
    {
        if (obj.Task2Started)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has started chrunching data: {obj.Task2Started}");
        }
        else if(obj.Task2Done)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has finished chrunching data: {obj.Task2Done}");
        }
        else if (obj.Task1Done)
        {
            Console.WriteLine($"Task no. {obj.TaskNo} has finished getting data: {obj.Task1Done}"); 
        }
    }


}

public class MyProgress
{
    public int TaskNo { get; set; }
    public bool Task1Done { get; set; }
    public bool Task2Done { get; internal set; }
    public bool Task2Started { get; internal set; }
}

public class Worker
{
    public int ID { get; set; }

    public Worker(int id)
    {
        ID = id;
    }
    public List<int> Datas { get; set; } = new List<int>() { 0, 0, 0 };
    public async Task GetDataAsync(IProgress<MyProgress> progress)
    {
        await Task.Delay(500);
        Datas = new List<int>() { 1, 2, 3 };
        progress.Report(new MyProgress() { TaskNo = ID, Task1Done = true });
    }

    public async Task CrunchData(IProgress<MyProgress> progress)
    {
        progress.Report(new MyProgress() { TaskNo = ID, Task2Started = true });
        await Task.Run(async () => { await Task.Delay(5000); Datas.Reverse(); });
        progress.Report(new MyProgress() { TaskNo = ID, Task2Done = true });
    }
}
class Program
{


    static async Task Main(string[] args)
    {
        var test = new TestMultiTask2();
        await test.TestListOfTasks();
        Console.WriteLine("Finished");
        Console.ReadLine();
    }
}
公共类测试多任务2
{
公共列表任务{get;private set;}
公共异步任务TestListOfTasks()
{
var workers=新列表();
var crunchingTasks=新列表();
var n=10;
对于(int i=0;i