1 c# parsing asynchronous httpclient task
我对异步任务有点陌生。
我有一个函数,可以获取学生 ID 并使用所需的 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);
}
}
Run Code Online (Sandbox Code Playgroud)
并且它工作正常。有时虽然我需要为很多学生运行这个函数,所以我使用以下命令
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}";
});
});
}
Run Code Online (Sandbox Code Playgroud)
我将任务存储在一个数组中以便稍后等待它们。
只要学生数量在 (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);
}
}
Run Code Online (Sandbox Code Playgroud)
其他方法可能会使用 .Net 类来利用生产者/消费者模式,例如BlockingCollection
| 归档时间: |
|
| 查看次数: |
1879 次 |
| 最近记录: |