Tengo un trabajo cron que llama a una tabla de base de datos y obtiene alrededor de medio millón de registros devueltos. Necesito recorrer todos esos datos y enviar publicaciones de API a una API de terceros. En general, esto funciona bien, pero el tiempo de procesamiento es eterno (10 horas). Necesito una manera de acelerarlo. He estado tratando de usar una lista de Tareas con SemaphoreSlim, pero tengo problemas (no me gusta que mi llamada API devuelva una Tarea). Me pregunto si alguien tiene una solución para esto que no destruya la memoria de la máquina virtual.
El código actual se parece a:
foreach(var data in dataList) { try { var response = await _apiService.PostData(data); _logger.Trace(response.Message); } catch// }
Pero estoy tratando de hacer esto y me sale mal la sintaxis:
var tasks = new List<Task<DataObj>>(); var throttler = new SemaphoreSlim(10); foreach(var data in dataList) { await throttler.WaitAsync(); tasks.Add(Task.Run(async () => { try { var response = await _apiService.PostData(data); _logger.Trace(response.Message); } finally { throttler.Release(); } })); }
Su lista es del tipo Task<DataObj>
, pero su lambda async
no devuelve nada, por lo que su tipo de devolución es Task
. Para corregir la sintaxis, simplemente devuelva el valor:
var response = await _apiService.PostData(data); _logger.Trace(response.Message); return response;
Como otros han señalado en los comentarios, también recomiendo no usar Task.Run
aquí. Un método async
local funcionaría bien:
var tasks = new List<Task<DataObj>>(); var throttler = new SemaphoreSlim(10); foreach(var data in dataList) { tasks.Add(ThrottledPostData(data)); } var results = await Task.WhenAll(tasks); async Task<DataObj> ThrottledPostData(Data data) { await throttler.WaitAsync(); try { var response = await _apiService.PostData(data); _logger.Trace(response.Message); return response; } finally { throttler.Release(); } }