es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

IHostedService para cambios en la base de datos se quedó colgado indefinidamente.

Estoy tratando de implementar notificaciones de cambios en la base de datos usando SignalR en una API web.
arriba está el código para NotificationService.cs

using System;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Options;
using Npgsql;
using webapi.DBCalls;
using webapi.Models;

namespace webapi.Notification
{
public class NotificationService : IHostedService
{
private IHubContext _hub;
private readonly ModelAppSettings _appSettings;
private DBInterceptor _db_interceptor;

public NotificationService(IHubContext<HubConfig> hub, IOptions<ModelAppSettings> appSettings)
{
    _appSettings = appSettings.Value;
    _db_interceptor = new DBInterceptor(_appSettings);
    _hub = hub;
}

public Task StartAsync(CancellationToken stoppingToken)
{
    onDataTableChangeListener();
    return Task.CompletedTask;
}

public void onDataTableChangeListener()
{
    using (var connection = new NpgsqlConnection(_appSettings.ConnectionString))
    {
        connection.Open();
        connection.Notification += (o, e) => notifyDataChange(e.Payload);
        using (var cmd = new NpgsqlCommand("LISTEN datachange", connection))
            cmd.ExecuteNonQuery();

        while (true)
            connection.Wait();
    }
}

public void notifyDataChange(string payload)
{
    // Hacer algo aquí
}

public Task StopAsync(CancellationToken stoppingToken)
{
    return Task.CompletedTask;
}

}
}

Y estoy registrando este servicio en Startup.cs en “ConfigurationService” como se muestra a continuación

services.AddHostedService();

Cuando ejecuto el programa, nunca se inicia y se queda colgado en la siguiente línea.

while (true)
connection.Wait();

Sé que necesito reescribir este método, pero no estoy seguro de cómo hacerlo.
Cualquier ayuda sería apreciada.

Tags:  , , ,

Answer

  1. Avatar for davy.ai

    Solución

    El problema con el código es que el método connection.Wait() está bloqueando el hilo y, por lo tanto, está haciendo que la aplicación se quede colgada. El método .Wait() no debería ser utilizado en un contexto asíncrono.

    Para solucionar esto, puedes reemplazar el bucle while(true) con una tarea asíncrona que espere un token de cancelación. Puedes utilizar el CancellationToken pasado en el método StartAsync de la siguiente manera:

    public async Task StartAsync(CancellationToken stoppingToken)
    {
        await Task.Run(() => onDataTableChangeListener(stoppingToken));
    }
    

    Luego, puedes modificar el método onDataTableChangeListener para que acepte un token de cancelación y lo utilice para salir del bucle, como se muestra a continuación:

    public void onDataTableChangeListener(CancellationToken cancellationToken)
    {
        using (var connection = new NpgsqlConnection(_appSettings.ConnectionString))
        {
            connection.Open();
            connection.Notification += (o, e) => notifyDataChange(e.Payload);
            using (var cmd = new NpgsqlCommand("LISTEN datachange", connection))
                cmd.ExecuteNonQuery();
    
            while (!cancellationToken.IsCancellationRequested)
            {
                // esperar la notificación de cambio de datos
                connection.Wait();
            }
        }
    }
    

    Con estos cambios, el código debería funcionar como se espera y la aplicación debería iniciarse sin bloquearse.

Comments are closed.