Tengo un Hub :
public sealed class NewValueHub : Hub { private IDataRelay _dataRelay; private IConfig _configurator; public NewValueHub(IDataRelay dataRelay, IConfig configurator) { _dataRelay = dataRelay; _configurator = configurator; _dataRelay.NewData += HandleNewData; //this gets unassigned on dispose. } public string GetMachineID() { IReadOnlyDictionary<string, string> config = _configurator.GetReadOnlyConfig(); string id; if (config.TryGetValue("machineID", out id)) { return id; } throw new HubException(Resource.machine_id_error); } private void HandleNewData(object? sender, string value) { Clients.All.SendAsync("ValueUpdate", value); } }Y un cliente javascript:
const connection = new signalR.HubConnectionBuilder().withAutomaticReconnect().withUrl("/newValueHub").build(); connection.on("ValueUpdate", function(value) { console.log(value); }); async function run(connection) { try { await connection.start(); let machineid = await connection.invoke('GetMachineID'); console.log('machine id', machineid); } catch (err) { console.error(err); } } run(connection); Sé que IDataRelay está funcionando, ya que otro subproceso está registrando valores en un archivo.
Cuando cargo la página, la consola registra la ID de la máquina, por lo que sé que la connection funciona.
Sin embargo, nunca veo ninguno de los nuevos valores en la consola.
Sé que los concentradores no existen por mucho tiempo, que es donde probablemente esté el problema, entonces, ¿qué se supone que debo hacer para manejar los eventos del servidor?
Quiero decir, cuando hay datos del IDataRelay , ¿cómo puedo hacer que SignalR se los envíe a mi cliente?
Quiere usar un servicio en segundo plano https://docs.microsoft.com/en-us/aspnet/core/signalr/background-services?view=aspnetcore-6.0#call-a-signalr-hub-from-a-background -servicio
En su caso, no tiene un bucle que deba esperar, por lo que puede conectar el controlador de eventos.
Sin embargo, no entiendo de dónde proviene el evento HandleNewData.
Según la sugerencia de davidfowl, he agregado un IHostedService que maneja el evento.
public class DataRelayWorker : IHostedService, IDisposable { private readonly IDataRelay _dataRelay; private readonly IHubContext<NewValueHub> _hubcontext; public DataRelayWorker(IDataRelay dataRelay, IHubContext<NewValueHub> context) { _dataRelay = dataRelay; _dataRelay.NewData += BoadcastValue; _hubContext = context; } private void BroadcastValue(object? sender, string value) { _hubcontext.Clients.All.SendAsync("ValueUpdate", value); } public void Dispose() { _dataRelay.NewData -= BoadcastValue; } } Esto se ejecuta agregando lo siguiente a Program.cs
builder.Services.AddHostedService<DataRelayWorker>(); Y eliminé todo lo que tenía que ver con IDataRelay del concentrador.