父-子任务-子任务需要花费时间来创建c#(性能问题)
本文关键字:子任务 性能 创建 问题 费时间 | 更新日期: 2023-09-27 18:06:46
我使用以下代码创建父和子任务。父任务的任务只是等待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);
编辑:应用程序太重(平均每秒5个请求),它应该在5秒内给出响应。
我正在使用task以获得更好的性能。除了任务之外,还有其他方法可以实现并行吗?
从评论来看,似乎每个WCF请求都需要来自10多个外部服务的响应。在这种情况下,最好异步调用每个服务,并等待await 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
也不阻塞。当await Task.WhenAll
被执行时,执行线程将被释放。一旦所有调用完成,执行将在await
行之后恢复。
结果是不需要创建父任务和子任务,因为TPL已经可以处理这个场景。开销很小,因为没有线程阻塞等待外部服务完成。
这意味着少量的线程可以处理大量的请求。
我引用@PanagiotisKanavos——没有理由让启动任务触发其他任务。您可能会遇到线程池耗尽的问题—一次只能创建这么多线程—之后您将不得不等待创建新线程;你也没有检查任务是否会完成(从可靠性的角度来看,这不是很好)
parentTask.Wait(5000);
将等待5秒并继续- parentTask
不会被杀死-它返回一个布尔值告诉您任务是否及时完成,但如果任务触发了新线程,则线程仍将运行。
如何强制低延迟&web服务执行一些冗长操作的可靠性:
- 将传入的请求持久化到持久存储(db, cloud等)
- 创建批处理应用程序(窗口服务),它将从队列中获取记录并执行它们
如果你的客户需要这个冗长操作的结果,你只有一个选择-扩大规模(web farm/cloud)。
还需要注意的是,更多的线程并不等于更好的性能——线程对于等待IO操作或者在有问题的机器上有多个内核是很好的,但是如果没有IO操作并且只有一个内核,你实际上会使你的代码变慢。
我建议你参考下面的组件,可能会解决你的问题。
章鱼。TaskTree
您可以灵活地在父任务上设置await
,以串行或并发的方式启动子任务。
请参考给出的代码片段,它可以使您清楚地了解组件的用途。