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

本文关键字:任务 运行 同步 应用程序 控制台 | 更新日期: 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));