В .NET 7 сервер Blazor с использованием https://stackexchange.github.io/StackExchange.Redis/Basics
Я пытаюсь понять, как подписаться на канал Redis, получать постоянные обновления и передавать эти обновления всем компонентам прослушивания. У меня настроена подписка, служба-посредник для передачи данных (которая работает) и прослушиватель в компоненте, который пытается получать постоянные обновления. Компонент не получает удар после вызова RedisService
.Invoke()
. Любая помощь по выкройке приветствуется.
Я попытался подключить ConnectionMultiplexer
к App.razor
, однако он не продолжает получать обновления прослушивателя подписки, когда я ухожу с домашней страницы.
Поэтому в Program.cs
я сделал следующее:
ConnectionMultiplexer redis = ConnectionMultiplexer.Connect(builder.Configuration.GetSection("RedisSettings").GetValue<string>("server"));
ISubscriber sub = redis.GetSubscriber();
sub.Subscribe(builder.Configuration.GetSection("RedisSettings").GetValue<string>("channel")).OnMessage(async channelMessage => {
await Task.Delay(1000);
if (!string.IsNullOrEmpty(channelMessage.Message))
{
var redis = builder.Services.BuildServiceProvider().CreateScope().ServiceProvider.GetRequiredService<RedisService>();
redis.Set(channelMessage.Message);
}
});
Мой RedisService прост. // SET ДЕЙСТВИТЕЛЬНО срабатывает несколько раз, когда я публикую новые данные в канал.
public string Message { get; private set; }
public event Action OnMessageChanged;
public void Set(string message)
{
Message = message;
OnMessageChanged?.Invoke();
}
В компоненте:
@inject RedisService _redis
protected override async Task OnInitializedAsync()
{
await base.OnInitializedAsync();
_redis.OnMessageChanged += HandleMessageChanged;
}
void HandleMessageChanged() // THIS DOESN'T GET HIT
{
}
Я также воспроизвел, что событие срабатывает несколько раз, если оно не указано в program.cs. Но если в program.cs, следующий код:
var redis = builder.Services.BuildServiceProvider().CreateScope().ServiceProvider.GetRequiredService<RedisService>();
на самом деле не получает тот же экземпляр «RedisService», который вы вводите с помощью @inject RedisService _redis
. Фактически создается новый экземпляр RedisService.
Вы можете рассмотреть возможность использования статического класса для «RedisService».
public static class RedisService
{
//create some flag to indcate if a component has been subscribed
public static bool HasSubScribeToHome { get; set; } = false;
public static bool HasSubScribeToCounter { get; set; } = false;
public static string Message { get; private set; }
public static event Action OnMessageChanged;
public static void Set(string message)
{
Message = message;
OnMessageChanged?.Invoke();
}
}
Тогда код будет выглядеть так
if (!string.IsNullOrEmpty(channelMessage.Message))
{
RedisService.Set(channelMessage.Message);
}
И компонент. (Проверьте, была ли подписка на компонент, чтобы предотвратить двойную подписку/триггер)
@page "/"
@using StackExchange.Redis
@code{
protected override void OnInitialized()
{
if (!RedisService.HasSubScribeToHome)
{
RedisService.OnMessageChanged += HandleMessageChanged;
RedisService.HasSubScribeToHome = true;
}
}
void HandleMessageChanged()
{
Console.WriteLine("called");
}
}
Результат теста