C#同时运行许多异步任务
问题描述:
我对于异步任务有点陌生。C#同时运行许多异步任务
我有一个功能,可以从特定的大学网站上获取学生证和数据,并提供所需的ID。
private static HttpClient client = new HttpClient();
public static async Task<Student> ParseAsync(string departmentLink, int id, CancellationToken ct)
{
string website = string.Format(departmentLink, id);
try
{
string data;
var stream = await client.GetAsync(website, ct);
using (var reader = new StreamReader(await stream.Content.ReadAsStreamAsync(), Encoding.GetEncoding("windows-1256")))
data = reader.ReadToEnd();
//Parse data here and return Student.
} catch (Exception ex)
{
Console.WriteLine(ex.Message);
}
}
它正常工作。虽然有时我需要为很多学生运行这个功能,所以我用下面的
for(int i = ids.first; i <= ids.last; i++)
{
tasks[i - ids.first] = ParseStudentData.ParseAsync(entity.Link, i, cts.Token).ContinueWith(t =>
{
Dispatcher.Invoke(() =>
{
listview_students.Items.Add(t.Result);
//Students.Add(t.Result);
//lbl_count.Content = $"{listview_students.Items.Count}/{testerino.Length}";
});
});
}
我存储在数组任务后等待他们。
只要学生人数介于(0,〜600?)之间,这也可以很好地工作,这是随机的。 然后对于仍然没有被解析过的所有其他学生抛出任务被取消。
请记住,我从不使用取消标记。
我需要在如此多的学生上运行这个函数,它可以完全达到〜9000个异步任务。那么发生了什么?
答
当您在如此短的时间内排队处理9000个请求时,您基本上会在网站上创建拒绝服务攻击。这不仅会导致你的错误,但它可能会使网站失效。最好将并发请求的数量限制在一个更合理的值(比如说30)。虽然有可能是几种方法可以做到这一点,我想到的是:
private async Task Test()
{
var tasks = new List<Task>();
for (int i = ids.first; i <= ids.last; i++)
{
tasks.Add(/* Do stuff */);
await WaitList(tasks, 30);
}
}
private async Task WaitList(IList<Task> tasks, int maxSize)
{
while (tasks.Count > maxSize)
{
var completed = await Task.WhenAny(tasks).ConfigureAwait(false);
tasks.Remove(completed);
}
}
其他方法可能利用使用.NET类生产者/消费者模式,如BlockingCollection