Saltar al contenido

Problemas de .net Core Parallel.ForEach

Hacemos una verificación profunda cada post en nuestro sitio web con el objetivo de mostrarte siempre la información más veraz y actual.

Solución:

Por qué Parallel.ForEach no es bueno para esta tarea se explica en los comentarios: está diseñado para tareas vinculadas a la CPU (uso intensivo de la CPU). Si lo usa para operaciones vinculadas a IO (como hacer solicitudes web), desperdiciará el hilo del grupo de subprocesos bloqueado mientras espera la respuesta, por nada bueno. Todavía es posible usarlo, pero no es lo mejor para este escenario.

Lo que necesita es usar métodos de solicitud web asincrónicos (como HttpWebRequest.GetResponseAsync), pero aquí surge otro problema: no desea ejecutar todas sus solicitudes web a la vez (como sugiere otra respuesta). Puede haber miles de URL (ID) en su lista. Entonces puede usar construcciones de sincronización de subprocesos diseñadas para eso, por ejemplo Semaphore. Semaphore es como una cola: permite que pasen X subprocesos, y el resto debe esperar hasta que uno de los subprocesos ocupados termine su trabajo (una descripción un poco simplificada). Aquí hay un ejemplo:

static async Task ProcessUrls(string[] urls) 
    var tasks = new List();
    // semaphore, allow to run 10 tasks in parallel
    using (var semaphore = new SemaphoreSlim(10)) 
        foreach (var url in urls) 
            // await here until there is a room for this task
            await semaphore.WaitAsync();
            tasks.Add(MakeRequest(semaphore, url));
        
        // await for the rest of tasks to complete
        await Task.WhenAll(tasks);
    


private static async Task MakeRequest(SemaphoreSlim semaphore, string url) 
    try 
        var request = (HttpWebRequest) WebRequest.Create(url);

        using (var response = await request.GetResponseAsync().ConfigureAwait(false)) 
            // do something with response    
        
    
    catch (Exception ex) 
        // do something
    
    finally 
        // don't forget to release
        semaphore.Release();
    

Ninguno de esos 3 enfoques son buenos.

No debe usar el Parallel clase, o Task.Run sobre este escenario.

En su lugar, tenga un async método del controlador:

private async Task HandleResponse(Task gettingResponse)

     HttpResponseMessage response = await gettingResponse;
     // Process the data

y luego usar Task.WhenAll:

Task[] requests = myList.Select(l => SendWebRequest(l.Id))
                        .Select(r => HandleResponse(r))
                        .ToArray();

await Task.WhenAll(requests);

Recuerda que tienes autorización de añadir un criterio certero si te ayudó.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *