我对异步任务不熟悉。
我有一个功能,可以获取学生ID并从特定的大学网站上删除所需的ID。
# open file
file = open("filename", "r")
# for each line the file 'filename'
for line in file:
# split the line in between spaces:
words = line.split(" ")
# get the columns by position:
level = words[2]
var_name_1 = words[4]
var_value_1 = words[6].split(",")[0] # get rid of ,
# etc
# do something here ...
# perhaps add to a list:
# array_value_1.append(var_value_1)
它运作正常。有时虽然我需要为很多学生运行这个功能所以我使用以下
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);
}
}
我将任务存储在一个数组中以便稍后等待它们。
只要学生数量介于(0,~600?)之间,它也可以很好地随机运行。 然后对于尚未解析的其他每个学生抛出任务被取消。
请记住,我从不使用取消令牌。
我需要在这么多学生身上运行这个功能,它可以完全达到~9000异步任务。那么发生了什么?
答案 0 :(得分:3)
当您在如此短的时间内排队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
答案 1 :(得分:0)
这是我根据@erdomke代码最终得到的结果:
public static async Task ForEachParallel<T>(
this IEnumerable<T> list,
Func<T, Task> action,
int dop)
{
var tasks = new List<Task>(dop);
foreach (var item in list)
{
tasks.Add(action(item));
while (tasks.Count >= dop)
{
var completed = await Task.WhenAny(tasks).ConfigureAwait(false);
tasks.Remove(completed);
}
}
// Wait for all remaining tasks.
await Task.WhenAll(tasks).ConfigureAwait(false);
}
// usage
await Enumerable
.Range(1, 500)
.ForEachParallel(i => ProcessItem(i), Environment.ProcessorCount);