Goal: foreach item in a list of S3 URIs, get the # of objects.
My .Net Core 3.1 Console app works great when run from VS 2019, but has problems when run from cmd (or Task Scheduler, .bat file, etc) once the list size gets above 5000 items or so.
Things seem okay until it gets down to around 500-1000 tasks remaining. Then, about 75% of the time, the remaining tasks never seem to complete and the app hangs forever... although the RAM usage dwindles down to just about nothing in Task Manager.
I'm fairly new to Async, and I've tried refactoring a bunch based on the myriad of solutions I see out there, but just can't seem to figure it out.
Items of note:
- In VS, tasks seem to come back faster over time, so my first 1000 tasks might take 10s, the next take 9s, etc. Outside of VS, it seems to be the opposite, they come back slower over time
- I run this app on an AWS EC2, a t3a.2xlarge w/ 32GB of RAM
- When I run it using PowerShell, sometimes during the run, it'll disconnect me from RDP, sometimes multiple times.
- In VS the app uses about 75MB w/ a small list of URIs, about about 600MB with a list of 150k. Outside of VS it uses about 4x more RAM.
- I tried compiling as both 32bit and 64bit
Code:
namespace MyNamespace
{
public class MyClass
{
private static DataTable dt;
private static IAmazonS3 clientS3;
static async Task Main(string[] args)
{
dt = <Call DB, get S3 URIs>;
clientS3 = new AmazonS3Client();
IEnumerable<Task<int>> callApiTasksQuery = from row in dt.AsEnumerable() select GetS3DataAsync(row);
List<Task<int>> apiTasks = callApiTasksQuery.ToList();
int total = 0;
while (apiTasks.Any())
{
// if (apiTasks.Count % 100 == 0) await Console.Out.WriteLineAsync($"{apiTasks.Count} remaining.");
Task<int> finishedTask = await Task.WhenAny(apiTasks);
apiTasks.Remove(finishedTask);
total += await finishedTask;
}
}
static async Task<int> GetS3DataAsync(DataRow row)
{
var response = await clientS3.ListObjectsV2Async(new ListObjectsV2Request { BucketName = row[0], Prefix = row[1] });
// Console.WriteLine(response.S3Objects.Count().ToString());
return 1;
}
}
}