Saltar al contenido

Volviendo al vacío desde un método de sincronización de C#

Es posible que a veces sea necesario definir un método que no sea un manejador de eventos o de devolución de llamada, pero que sea similar en el sentido de que los que llaman al método no necesitan preocuparse por el resultado. Por ejemplo, tal vez quieras publicar una llamada a la API en un servidor remoto que recopile los análisis. No necesitas una barra de progreso, y el usuario no necesita saber cuándo terminó, o incluso si falló. Este tipo de cosas pueden llamarse “disparar y olvidar”, y a veces los desarrolladores utilizan un método de sincronización que devuelve el vacío por eso. Para continuar con nuestro ejemplo anterior, digamos que un clic en el botón “Generar” también debería intentar registrar ese clic en un servidor remoto.

123456789101112131415 EvitarIniciar(){ generarBotón.OnClick += OnGenerarBotónClick;} EvitarEvitarGenerarBotónClick(){AcciónPostanalítica("generarBotónClick");GenerarImagen();}así EvitarAcciónPostanalítica(cadena de acciónNombre){awaitnewHttpClient(). PostAsync("https://...",newStringContent(actionName));}

csharp

Volviendo al vacío desde un método de sincronización de C#Volviendo al vacío desde un método de sincronización de C#

En el ejemplo anterior, PostAnalyticAction es el método “dispara y olvida”. Este método se espera a propósito y no , por lo que la ejecución de OnGenerateButtonClicked continuará antes de que se complete PostAnalyticAction. Esto permite que la generación de la imagen comience antes de que se reciba una respuesta del servidor de análisis remoto.

Si bien ese enfoque de “disparar y olvidar” puede funcionar bien en muchos casos, se desaconseja. Recuerde que, la mayoría de las veces, la elección correcta es devolver la tarea de los métodos de sincronización, a menos que se trate de un manejador de eventos o una llamada de retorno. En este ejemplo, PostAnalyticAction no es ni , y se llama explícitamente en lugar de implícitamente, lo que sugiere que el llamador (OnGenerateButtonClicked) puede estar interesado en el resultado (incluyendo cualquier excepción que pueda surgir en él).

Un mejor enfoque sería devolver la tarea de PostAnalyticAction y esperarla en OnGenerateButtonClicked. Esto requerirá que OnGenerateButtonClicked sea marcado como async.

Si se te ocurrió ese pensamiento, ¡buen trabajo! Tienes razón. Ya no estamos “olvidando” nuestro método ahora; estamos esperando a que termine. Podemos “arreglarlo” haciendo que el análisis sea lo último que hagamos. Si no hay un código después de la espera, nada se retrasa por el tiempo de espera. Aquí está la muestra de código actualizado:

12345678910así que evita el botón de generación de click(){GenerateImage();awaitPostAnalyticAction("generar botón de click");}asyncTaskPostAnalyticAction(string actionName){awaitnewHttpClient().PostAsync("https://...",newStringContent(actionName));}

csharp

Fíjate que ahora el único método de vacío asíncrono que tenemos es OnGenerateButtonClicked, que es un manejador de eventos. A menudo encontrarás que, con una refactorización cuidadosa, puedes evitar la necesidad de “disparar y olvidar”. Si el código de reordenación no funciona, considera un enfoque de acoplamiento suelto, de tal manera que no estés llamando directamente al método en cuestión. Por ejemplo, podrías usar algún tipo de mensaje de publicación/suscripción, o incluso una colección de hilos seguros, en la que se añade a la colección de forma sincronizada, y un hilo separado que monitoriza los nuevos elementos. Sin embargo, tu primera opción siempre debería ser usar la tarea en conjunto con la espera.