I have a 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);
}
}
And a javascript client:
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);
I know the IDataRelay
is working, as another thread is logging values to a file.
When I load the page, the console logs the machine ID, so I know the connection
works.
However I'm never seeing any of the new values in the console.
I know that hubs don't exist for long, which is where the problem probably is, so what am I meant to do to handle the server events?
I mean, when there is data from the IDataRelay
, how can I get signalR to send it to my client?
CodePudding user response:
You want to use a background service https://docs.microsoft.com/en-us/aspnet/core/signalr/background-services?view=aspnetcore-6.0#call-a-signalr-hub-from-a-background-service.
In your case, you don't have a loop that needs to await so you can just wire up the event handler.
I don't understand where the HandleNewData event comes from though.
CodePudding user response:
As per davidfowl's suggestion I have added an IHostedService
that handles the event.
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;
}
}
This is run by adding the following to Program.cs
builder.Services.AddHostedService<DataRelayWorker>();
And I have removed anything to do with the IDataRelay
from the hub.