Я пытаюсь внедрить SignalR
в проект WorkerService
, а затем имитировать уведомления на стороне сервера.
Далее в моем файле Worker.cs
я получаю несколько нулевых ссылок, что говорит мне о том, что я изначально не являюсь должным образом своим объектом Hub.
Сначала я создал NotificationHub solution
с одноименным проектом.
Вот Notifications.cs
- отлично работает.
using Microsoft.AspNetCore.SignalR;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
namespace NotificationHub.Hubs
{
public interface IHubClient
{
Task MessageReceived(string user, string message);
Task MessageReceived(string message);
}
public class Notifications: Hub<IHubClient>
{
[HubMethodName("SendMessageToClient")]
public async Task SendMessage(string username, string message)
{
await Clients.All.MessageReceived(username, "from Notification Hub:" + message);
}
public override Task OnConnectedAsync()
{
Groups.AddToGroupAsync(Context.ConnectionId, "SignalR Users");
_ = SendMessage("From Server", "Hub reconnected on server.");
return base.OnConnectedAsync();
}
public override Task OnDisconnectedAsync(Exception exception)
{
Console.Write("Hub just disconnected on server.");
return base.OnDisconnectedAsync(exception);
}
}
}
NotificationHub
работает в IIS на моем локальном компьютере, что позволяет мне вызывать Notification Hub из моего TypeScript
клиента.
то есть я просто добавил простой HTML button
для запуска сообщения от клиента. Моя функция срабатывает:
this.hubConnection.send('SendMessageToClient', 'client', `Message from client side. ${today}`)
.then(() => console.log('Message sent from client.'));
Core WorkerService: моя проблема здесь
Затем я добавил NotificationWorkService, в который я пытаюсь внедрить SignalR. Цель состоит в том, чтобы в конечном итоге эта служба работала на сервере Windows, который регулярно проверяет наличие уведомлений и доставляет их в браузер.
В моем проекте WorkerService вот Program.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
namespace HarmonyNotificationWorkerService
{
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
public static IHostBuilder CreateHostBuilder(string[] args) =>
Host.CreateDefaultBuilder(args)
.ConfigureServices((hostContext, services) =>
{
services.AddHostedService<Worker>();
});
}
}
а вот Worker.cs
-
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.AspNet.SignalR.Client;
using Microsoft.AspNetCore.SignalR;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using NotificationHub.Hubs;
namespace HarmonyNotificationWorkerService
{
public interface IHubClient
{
Task MessageReceived(string user, string message);
Task MessageReceived(string message);
}
public class Worker : BackgroundService
{
private IHubContext<Notifications> _hubContext;
private readonly Hub<IHubClient> _hubNotif;
private readonly ILogger<Worker> _logger;
public Worker(ILogger<Worker> logger)
{
_logger = logger;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
using (var hubConnection = new HubConnection("/hub"))
{
IHubProxy hubproxy = hubConnection.CreateHubProxy("https://localhost:44311/hub");
await hubproxy.Invoke("SendMessage", "test");
}
while (!stoppingToken.IsCancellationRequested)
{
_logger.LogInformation("Worker running at: {time}", DateTimeOffset.Now);
await Task.Delay(1000, stoppingToken);
}
}
private async Task CheckForNotifications()
{
await _hubNotif.Clients.All.MessageReceived("from work server", "Dude, you've got mail!");
}
}
}
ПРОБЛЕМА:
Проблема в том, что объекты _hubContext
и _hubNotif
всегда нулевые, поэтому я не могу проверить ни один из них. Я изначально не понимаю их правильно, но я не уверен, как это сделать. С# также показывает мне предупреждение об этой нулевой ссылке.
System.InvalidOperationException: «Данные не могут быть отправлены, так как соединение находится в отключенном состоянии. Запуск вызова перед отправкой любых данных.`
ОБНОВЛЕНИЕ: УСТАНОВИТЕ КЛИЕНТСКИЙ ПАКЕТ SIGNALR
Я добавил using Microsoft.AspNetCore.SignalR.Client;
к Worker.cs
и установил private readonly HubConnection _hubConnection;
вверху класса Worker
.
Затем я изменил следующий метод, чтобы проверить состояние подключения, а затем отправить сообщение:
private async Task CheckForNotifications()
{
if (_hubConnection.State == HubConnectionState.Disconnected)
{
await _hubConnection.StartAsync();
}
_ = _hubConnection.SendAsync("SendMessageToClient", "from service worker", "You've got mail!");
}
Вроде все успешно работает.
Поток действительно завершается с code 0
время от времени, но я считаю, что в данном случае это нормально, так как я работаю на Task.Delay(5000);
Call start before sending any data.
т.е.await hubConnection.Start();
- person Nkosi   schedule 26.06.2020Start()
. Вероятно, это потому, что я должен был использоватьMicrosoft.AspNetCore.SignalR.Client
в своем сервисе, подобно тому, как я использую'@microsoft/signalr'
в TypeScript для своего браузерного приложения Angular. - person bob.mazzo   schedule 26.06.2020messageReceived
. Однако мой сервис вылетает через несколько секунд с ошибкой. Сначала вы видите, что мой_logger
работает нормально, затемthread has exited with code 0
==›NotificationWorkerService.Worker: Information: Worker running at: 06/26/2020 11:08:32 -04:00 Exception thrown: 'System.InvalidOperationException' in System.Private.CoreLib.dll
- person bob.mazzo   schedule 26.06.2020IHostBuilder CreateHostBuilder
, что вызывало исключение. Я сожалею о том, что. Кажется, теперь все работает. Я также проверяю состояниеif (_hubConnection.State == HubConnectionState.Disconnected)
, что делает его чище. Можете ли вы добавить свой комментарий в качестве ответа? Я счастлив выбрать его. - person bob.mazzo   schedule 26.06.2020