在递归函数使用异步/等待时控制任务总数 [英] Control total number of tasks when using Async/Await in a recursive function
问题描述
我写了这个code。递归通过REST调用将在Web系统文件夹。
因此,基本上,它为根节点的文件夹,然后获取所有子节点和平行并递归调用自身。 (每个孩子)
与code中的唯一的问题是,如果一个节点有太多可能的儿童,或者层次太深的话,我开始变得TaskCancellation错误。
我已经尝试增加超时10分钟..但是这并没有解决问题。
所以我的问题是我怎么能开始说50的任务,然后等待事情得到释放,继续只有当在50开放式插槽
目前我觉得我的code是创建任务将没有任何限制的是流经层次。
公共异步任务CreateSPFolder(节点的节点,HttpClient的客户端,串docLib,字符串currentPath = NULL)
{
串节点名称= Uri.EscapeDataString(节点名称);
VAR要求=新的{__metadata =新的{TYPE =SP.Folder},ServerRelativeUrl =节点名称};
字符串jsonRequest = JsonConvert.SerializeObject(请求);
的StringContent strContent =新的StringContent(jsonRequest);
strContent.Headers.ContentType = MediaTypeHeaderValue.Parse(应用/ JSON; ODATA =冗长);
HTT presponseMessage RESP =等待client.PostAsync(CMD,strContent);
如果(resp.IsSuccessStatus code)
{
currentPath =(currentPath == NULL)?节点名称:currentPath +/+节点名称;
}
其他
{
字符串内容=等待resp.Content.ReadAsStringAsync();
Console.WriteLine(内容);
抛出新的异常(无法创建文件夹+内容);
}
} 清单<任务> Tasklist命令=新的List<任务>();
。node.Children.ToList()的ForEach(C => taskList.Add(CreateSPFolder(三,客户机,docLib,currentPath)));
Task.WaitAll(taskList.ToArray());
}
您可以使用 SemaphoreSlim
来控制并发任务的数量。在初始化信号量你想有,然后每次执行你获得的信号,然后再释放,当你与任务完成了任务的最大任务数。
这是运行永远使用随机数,并在同一时间执行最多2任务的code的稍微简化版本
类节目
{
私有静态SemaphoreSlim信号=新SemaphoreSlim(2,2); 公共静态异步任务CreateSPFolder(INT文件夹)
{
尝试
{
等待semaphore.WaitAsync();
Console.WriteLine(执行+文件夹);
Console.WriteLine(WaitAsync - CURRENTCOUNT+ semaphore.CurrentCount); 等待Task.Delay(2000);
}
最后
{
Console.WriteLine(执行完毕+文件夹);
semaphore.Release();
Console.WriteLine(释放 - CURRENTCOUNT+ semaphore.CurrentCount);
} VAR兰特=新的随机();
变种下一= rand.Next(10);
VAR孩子= Enumerable.Range(1,下一个).ToList(); Task.WaitAll(children.Select(CreateSPFolder).ToArray());
} 静态无效的主要(字串[] args)
{
CreateSPFolder(1).Wait(); Console.ReadKey();
}
}
I have written this code. It recursively creates folders in the web system by making REST Calls. So basically, it creates a folder for the root node, then gets all the child nodes and parallely and recursively calls itself. (for each child)
the only problem with the code is that if a node has too may children OR if the hierarchy is too deep, then I start getting "TaskCancellation" errors.
I have already tried increasing the timeout to 10 minutes.. but that does not solve the problem.
So my question is how can I start say 50 tasks, then wait for something to get freed and proceed only when there is an open slot in 50.
Currently I think my code is going on creating tasks without any limit as is flows through the hierarchy.
public async Task CreateSPFolder(Node node, HttpClient client, string docLib, string currentPath = null)
{
string nodeName = Uri.EscapeDataString(nodeName);
var request = new { __metadata = new { type = "SP.Folder" }, ServerRelativeUrl = nodeName };
string jsonRequest = JsonConvert.SerializeObject(request);
StringContent strContent = new StringContent(jsonRequest);
strContent.Headers.ContentType = MediaTypeHeaderValue.Parse("application/json;odata=verbose");
HttpResponseMessage resp = await client.PostAsync(cmd, strContent);
if (resp.IsSuccessStatusCode)
{
currentPath = (currentPath == null) ? nodeName : currentPath + "/" + nodeName;
}
else
{
string content = await resp.Content.ReadAsStringAsync();
Console.WriteLine(content);
throw new Exception("Failed to create folder " + content);
}
}
List<Task> taskList = new List<Task>();
node.Children.ToList().ForEach(c => taskList.Add(CreateSPFolder(c, client, docLib, currentPath)));
Task.WaitAll(taskList.ToArray());
}
You can use a SemaphoreSlim
to control the number of concurrent tasks. You initialize the semaphore to the maximum number of tasks you want to have and then each time you execute a task you acquire the semaphore and then release it when you are finished with the task.
This is a somewhat simplified version of your code that runs forever using random numbers and executes a maximum of 2 tasks at the same time.
class Program
{
private static SemaphoreSlim semaphore = new SemaphoreSlim(2, 2);
public static async Task CreateSPFolder(int folder)
{
try
{
await semaphore.WaitAsync();
Console.WriteLine("Executing " + folder);
Console.WriteLine("WaitAsync - CurrentCount " + semaphore.CurrentCount);
await Task.Delay(2000);
}
finally
{
Console.WriteLine("Finished Executing " + folder);
semaphore.Release();
Console.WriteLine("Release - CurrentCount " + semaphore.CurrentCount);
}
var rand = new Random();
var next = rand.Next(10);
var children = Enumerable.Range(1, next).ToList();
Task.WaitAll(children.Select(CreateSPFolder).ToArray());
}
static void Main(string[] args)
{
CreateSPFolder(1).Wait();
Console.ReadKey();
}
}
这篇关于在递归函数使用异步/等待时控制任务总数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!