父子任务-子任务需要时间来创建C#(性能问题)

父子任务-子任务需要时间来创建C#(性能问题),c#,multithreading,task,C#,Multithreading,Task,我使用以下代码创建父任务和子任务。父任务的作业只需等待5秒,子任务执行并将结果存储在共享资源中。 我已经标记出子任务需要时间 实际上我不知道当创建子线程并开始并行执行时的内部机制 是否有我可以知道的任何文档,或者是否有其他最好的方法来实现父子概念 List<Task> taskList = new List<Task>(); Task parentTask = Task.Factory.StartNew(() => { int index = 0;

我使用以下代码创建父任务和子任务。父任务的作业只需等待5秒,子任务执行并将结果存储在共享资源中。 我已经标记出子任务需要时间

实际上我不知道当创建子线程并开始并行执行时的内部机制

是否有我可以知道的任何文档,或者是否有其他最好的方法来实现父子概念

List<Task> taskList = new List<Task>();

Task parentTask = Task.Factory.StartNew(() =>
{
    int index = 0;
    for (int i = 0; i < 10; i++)
    {
        var task = new Task(() => PrintHello(), TaskCreationOptions.AttachedToParent);
        taskList.Add(task);
        index++;
    }
    foreach (Task task in taskList)
    {
        task.Start();
    }
});

//Wait Parent Task.
parentTask.Wait(5000);
List taskList=new List();
Task parentTask=Task.Factory.StartNew(()=>
{
int指数=0;
对于(int i=0;i<10;i++)
{
var task=新任务(()=>PrintHello(),TaskCreationOptions.AttachedToParent);
任务列表。添加(任务);
索引++;
}
foreach(任务列表中的任务)
{
task.Start();
}
});
//等待父任务。
parentTask.Wait(5000);
编辑:

应用程序太重(平均每秒5个请求),应在5秒内给出响应

我使用任务来提高性能。
除了task之外,还有其他方法来实现并行性吗?

我将引用@PanagiotisKanavos-没有理由让startup task触发其余任务。您可能遇到了线程池不足的问题—一次只能创建这么多线程—之后您必须等待创建新线程;此外,您没有检查任务是否会完成(从可靠性的角度来看,这不是很好)

只需等待5秒并继续-不会终止
parentTask
-它返回一个布尔值,告诉您任务是否及时完成,但如果任务触发了新线程,线程仍将运行

如何强制Web服务执行一些长时间操作的低延迟和可靠性:

  • 将传入请求持久化到持久存储(db、云等)
  • 创建批处理应用程序(窗口服务),该应用程序将从队列中获取记录并执行这些记录
  • 如果您的客户需要这一冗长操作的结果,那么您只有一个选择—向上扩展(web场/云)


    还要注意的是,更多的线程并不意味着更好的性能-线程对于等待IO操作或者如果您有多个内核在讨论中,那么线程是非常好的,但是如果没有IO操作,只有一个内核,那么实际上您正在使代码变慢。

    从注释中可以看出,似乎每个WCF请求都需要来自10多个外部服务的响应。在这种情况下,最好异步调用每个服务,并使用
    wait Task.WhenAll(tasks)等待所有生成的任务完成,例如:

    public async Task CallManyMethods(string someData)
    { 
        var tasks=new []{
            CallSvc1Async(someData),
            CallSvc2Async(someData),
        }
        var results=await Task.WhenAll(tasks);
        ...
        //Unpack the results and keep processing them
    }
    
    public async Task<string> CallSvc1Async(string someData)
    {
        var response=await _svc1Proxy.GetStuffAsync(someData);
        //build a result from the response
        return result;
    }
    
    public async Task<string> CallSvc2Async(string someData)
    {
        var url=....
        var json=await _httpClient.GetStringAsync(url);
        ....
        return result;
    }
    
    公共异步任务CallManyMethods(字符串someData)
    { 
    var tasks=new[]{
    CallSvc1Async(某些数据),
    CallSvc2Async(someData),
    }
    var结果=等待任务.WhenAll(任务);
    ...
    //将结果解压缩并继续处理
    }
    公共异步任务调用Svc1Async(字符串someData)
    {
    var response=await_svc1Proxy.GetStuffAsync(someData);
    //根据响应生成结果
    返回结果;
    }
    公共异步任务CallSvc2Async(字符串someData)
    {
    变量url=。。。。
    var json=await\u httpClient.GetStringAsync(url);
    ....
    返回结果;
    }
    
    所有方法返回的字符串仅用于演示目的

    每个方法将向外部服务发送调用,然后释放其线程,直到收到响应。这样,线程就不会被阻塞等待响应,总等待时间只由最慢的外部服务决定

    CallManyMethods
    也不会阻止。执行线程将在
    等待任务时释放。所有
    执行时释放。一旦所有调用完成,执行将在
    wait
    行之后恢复

    结果是不需要创建父任务和子任务,因为TPL已经可以处理这个场景了。开销最小,因为没有线程块等待外部服务完成


    这意味着少量线程可以处理数量多得多的请求。

    任务不是线程。您不必在这里创建新线程。线程没有父线程。任务可以有父母。你想解决的实际问题是什么?为什么要在任务之间建立父子关系?你为什么创造冷任务?几乎可以肯定,有更好的方法来解决实际问题。例如,使用
    Parallel.Invoke
    或使用
    Task.whalll
    等待一个活动数组的完成tasks@Gusdor-你说得对。我的意思是儿童任务需要时间。线程和任务与我发现的不同。请查看System.ComponentModel。BackgroundWorker@AdamFinleyBackgroundWorker已经过时,只适用于WinForms应用程序。它不能在不同的任务之间创建任何类型的关系,执行连续性等。它本质上与调用
    任务相同。运行
    并使用
    进度
    对象来报告事件,只需要组件开销,无法组合多个操作。Application server有8个核心和16 GB RAM。是的,所有10到12个任务都没有IO操作,但我希望所有任务都应该并行、快速运行,并在4到5秒内返回每个任务的结果。还有其他并行方式吗?如果他执行的是IO广泛而不是CPU密集型的操作,异步IO肯定是一种方式。@Panagiotis Kanavos-谢谢你的回答!你们是对的,我可以使用这个方法,但我认为,当所有异步方法都执行时,Task.whalll(任务)就会执行。若异步方法花费的时间超过5秒,那个么我不想等待asyn方法,而想继续使用主线程。
    
    public async Task CallManyMethods(string someData)
    { 
        var tasks=new []{
            CallSvc1Async(someData),
            CallSvc2Async(someData),
        }
        var results=await Task.WhenAll(tasks);
        ...
        //Unpack the results and keep processing them
    }
    
    public async Task<string> CallSvc1Async(string someData)
    {
        var response=await _svc1Proxy.GetStuffAsync(someData);
        //build a result from the response
        return result;
    }
    
    public async Task<string> CallSvc2Async(string someData)
    {
        var url=....
        var json=await _httpClient.GetStringAsync(url);
        ....
        return result;
    }