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
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.
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 elCancellationToken
pasado en el métodoStartAsync
de la siguiente manera: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:Con estos cambios, el código debería funcionar como se espera y la aplicación debería iniciarse sin bloquearse.