我有控制台应用程序,它通过HTTP执行多个API请求 在单线程中运行时,它最多可以执行大约8个API请求/秒。
接收API调用的服务器有很多免费资源,因此它应该可以处理超过8秒的时间。
此外,当我运行应用程序的多个实例时,每个实例仍然能够执行8个请求/秒。
我尝试使用代码来并行化请求,但它仍然可以同步运行:
class element
{
public:
element() {}
// the rest
};
我在这里做错了什么?
修改 我的错误是迭代任务并获得task.Result,这阻止了主线程,让我觉得它是同步运行的。
我最终使用的代码而不是foreach(taskList中的var任务):
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);
}
答案 0 :(得分:3)
可能会发生一些事情。
首先,.net ServicePoint
类默认允许每个主机最多2个连接。请参阅this Stack Overflow question/answer。
其次,您的服务器理论上可能能够处理超过8秒/秒,但可能存在资源限制或其他问题阻止服务器端。我遇到了API调用的问题,理论上应该能够处理比它们更多的问题,但出于任何原因设计或实现不正确。
答案 1 :(得分:2)
@theMayer有点正确。您对apiRequest的调用可能会阻止并使整个表达看起来是同步的......
然而......你正在迭代每个任务并调用task.Result,它将阻塞直到任务完成以便将其打印到屏幕上。因此,例如,除了第一个任务之外的所有任务都可以完成,但是在第一个完成之前你不会打印它们,并且你将继续按顺序打印它们。
稍微不同的是,你可以像这样更简洁地重写这个:
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));