控制台应用程序中同步运行的任务
本文关键字:任务 运行 同步 应用程序 控制台 | 更新日期: 2023-09-27 18:10:16
我有一个控制台应用程序,它通过HTTPs做多个API请求。
当在单线程中运行时,它最多可以做大约8个API请求/秒。
正在接收API调用的服务器有很多空闲资源,所以它应该能够处理超过8个/秒。
同样,当我运行应用程序的多个实例时,每个实例仍然能够做8个请求/秒。
我尝试了以下代码来并行处理请求,但它仍然同步运行:
var taskList = new List<Task<string>>();
for (int i = 0; i < 10000; i++)
{
string threadNumber = i.ToString();
Task<string> task = Task<string>.Factory.StartNew(() => apiRequest(requestData));
taskList.Add(task);
}
foreach (var task in taskList)
{
Console.WriteLine(task.Result);
}
我在这里做错了什么?
编辑:我的错误是迭代任务并获得任务。结果,阻塞了主线程,使我认为它是同步运行的。
我最终使用的代码,而不是foreach(var task in taskList):
while (taskList.Count > 0)
{
Task.WaitAny();
// Gets tasks in RanToCompletion or Faulted state
var finishedTasks = GetFinishedTasks(taskList);
foreach (Task<string> finishedTask in finishedTasks)
{
Console.WriteLine(finishedTask.Result);
taskList.Remove(finishedTask);
}
}
可能有两件事正在发生。首先,默认情况下,.net ServicePoint
类允许每个主机的最大连接数为2。请看这个堆栈溢出问题/答案。
第二,你的服务器理论上可以处理超过8个/秒,但是在服务器端可能存在资源限制或其他问题。我遇到过API调用的问题,理论上应该能够处理比它们做的更多,但无论出于何种原因,设计或实现不当。
@theMayer是正确的。这是可能的,你的调用apiRequest是什么阻塞和使整个表达式似乎同步…
然而…你遍历每个任务并调用task。结果,它将阻塞直到任务完成,以便将其打印到屏幕上。因此,例如,除了第一个任务之外的所有任务都可以完成,但是在第一个任务完成之前您不会打印它们,并且您将继续按顺序打印它们。
稍微不同的是,您可以更简洁地重写如下:
var screenLock = new object();
var results = Enumerable.Range(1, 10000)
.AsParallel()
.Select(i => {
// I wouldn't actually use this printing, but it should help you understand your example a bit better
lock (screenLock) {
Console.WriteLine("Task i");
}
apiRequest(requestedData));
});
如果不打印,它看起来像这样:
var results = Enumerable.Range(1, 10000)
.AsParallel()
.Select(i => apiRequest(requestedData));