none
Llamar a un método en otro hilo RRS feed

  • Pregunta

  • Buenas,

    Tengo un método como el siguiente:

    [HttpPost]
    public async Task<ActionResult> EnviarCorreoMasivo(int[] IdsPersona)
    {
    	foreach (int id in IdsPersona)
    	{
    		var datos = await service.Get(id);
    		
    		// ...
    		
    		Task.Run(() => emailService.SendAsync(datos));
    	}
    	
    	return StatusCode(StatusCodes.Status200OK, response);
    }

    La llamada a emailService.Send(), tarda alrededor de 10 segundos en completarse, y mientras tanto, como en la app se está utilizando un loading le deja bloqueada la pantalla al usuario. Pretendo hacer que esa llamada se ejecute en segundo plano y para ello estoy creando un hilo, sin embargo, me está marcando la siguiente advertencia:

    Severity Code Description Project File Line Suppression State
    Warning CS4014 Because this call is not awaited, execution of the current method continues before the call is completed. Consider applying the 'await' operator to the result of the call.

    Entiendo que se debe a que estoy llamando a un método asíncrono sin uitlizar el operador await, pero eso haría que la ejecución se detenga a espera y volvería a tener el mismo problema.

    Favor si me orientan, muchas gracias.



    • Editado eduar2083 jueves, 7 de mayo de 2020 22:10
    jueves, 7 de mayo de 2020 22:08

Respuestas

  • hola

    Pero "service.Get()" se implementa como asincrono ? no sera que deba ser

    [HttpPost]
    public async Task<ActionResult> EnviarCorreoMasivo(int[] IdsPersona)
    {
    	foreach (int id in IdsPersona)
    	{
    		var datos = service.Get(id);
    		
    		// ...
    		
    		await emailService.SendAsync(datos);
    	}
    	
    	return StatusCode(StatusCodes.Status200OK, response);
    }

    no muestras el codigo del Get() pero no veo que este tenga que ser asincrono

    Igual un item, que sea asincrono no quiere decir que va a enviar mail en paralelo, si querias algo asi deberias usar el

    Procedimiento Escribir un bucle Parallel.ForEach sencillo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 8 de mayo de 2020 19:47
  • Hola, la respuesta de CppMiguel es correcta aunque debería explicar su código. Lo que está implementando es generar una lista de tareas y después en la última línea lo que hace es lanzarlas todas a la vez aprovechando las capacidades multihilo. El resultado? El tiempo de ejecución tardará únicamente lo que tarde la tarea más pesada en ejecutarse. Me explico. En tu código lo que haces por ejemplo es ejecutar 10 veces el bucle.cada llamada tarda 1seg,pof lo que el tiempo de ejecución total serían 10seg. En cambio con el código de CppMiguel, la ejecución tardará 1seg únicamente (más o menos depende de otros factores como tu procesador, la memoria etc....). Se consigue rebajar 10 veces el tiempo! 

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    sábado, 9 de mayo de 2020 22:20
    Moderador

Todas las respuestas

  • hola

    Pero "service.Get()" se implementa como asincrono ? no sera que deba ser

    [HttpPost]
    public async Task<ActionResult> EnviarCorreoMasivo(int[] IdsPersona)
    {
    	foreach (int id in IdsPersona)
    	{
    		var datos = service.Get(id);
    		
    		// ...
    		
    		await emailService.SendAsync(datos);
    	}
    	
    	return StatusCode(StatusCodes.Status200OK, response);
    }

    no muestras el codigo del Get() pero no veo que este tenga que ser asincrono

    Igual un item, que sea asincrono no quiere decir que va a enviar mail en paralelo, si querias algo asi deberias usar el

    Procedimiento Escribir un bucle Parallel.ForEach sencillo

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    viernes, 8 de mayo de 2020 19:47
  • Hola Leandro,

    service.Get(Id) realiza una consulta a la Base de Datos utilizando EF-Core y sí es un método asíncrono porque en la infraestructura hace un FirstOrDefaultAsync(), dicha operación es bastante rápida, el await hace que se detenga menos de 1 segundo. El problema es la llamada a emailService.SendAsync() que tarda alrededor de 10 segundos cada envío de email.

    Estoy intentando utilizar el Paraller.ForEach pero dentro de dicho bucle me marca error en la llamada al método asíncrono service.Get()

    viernes, 8 de mayo de 2020 22:00
  • hola

    >>El problema es la llamada a emailService.SendAsync() que tarda alrededor de 10 segundos cada envío de email.

    ok entonces el Get() es correcto como lo defines, pero intentaste cambiar el SendAsync() quitando el Task y solo usando el await?

    >>pero dentro de dicho bucle me marca error en la llamada al método asíncrono service.Get()

    si solo dices que marca error no veo como podria ayudarte solo con ese dato, no pones el codigo que estas usando ni cual es el mensaje del error

    saludos


    Leandro Tuttini

    Blog
    MVP Profile
    Buenos Aires
    Argentina

    sábado, 9 de mayo de 2020 5:45
  • Deleted
    sábado, 9 de mayo de 2020 17:22
  • Hola, la respuesta de CppMiguel es correcta aunque debería explicar su código. Lo que está implementando es generar una lista de tareas y después en la última línea lo que hace es lanzarlas todas a la vez aprovechando las capacidades multihilo. El resultado? El tiempo de ejecución tardará únicamente lo que tarde la tarea más pesada en ejecutarse. Me explico. En tu código lo que haces por ejemplo es ejecutar 10 veces el bucle.cada llamada tarda 1seg,pof lo que el tiempo de ejecución total serían 10seg. En cambio con el código de CppMiguel, la ejecución tardará 1seg únicamente (más o menos depende de otros factores como tu procesador, la memoria etc....). Se consigue rebajar 10 veces el tiempo! 

    Si se solucionó tu consulta no olvides marcar la respuesta. Si te ayudó, vótala como útil. Saludos

    sábado, 9 de mayo de 2020 22:20
    Moderador