在控制台应用程序中同步运行的任务

时间:2015-08-27 14:36:25

标签: c# multithreading task-parallel-library asp.net-web-api

我有控制台应用程序,它通过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);
}

2 个答案:

答案 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));