web-dev-qa-db-ja.com

SignalRHubの呼び出しがAsp.NetCore WebAPIで機能しない

私はSignalRの初心者です。 Asp.Net Core WebAPIをセットアップして、他のクライアントがSignalRを使用してそれに接続し、リアルタイムデータを取得できるようにしようとしています。私のハブクラスは次のとおりです。

_public class TimeHub : Hub
{
    public async Task UpdateTime(string message)
    {
        await Clients.All.SendAsync("ReceiveMessage", message);
    }
}
_

私は次のようなリレークラスを持っています:

_public class TimeRelay : ITimeRelay
{
    private readonly IHubContext<TimeHub> _timeHubContext;

    public TimeRelay(IHubContext<TimeHub> context)
    {

        _timeHubContext = context;
        Task.Factory.StartNew(async () =>
        {
            while (true)
            {
                await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());
                Thread.Sleep(2000);
            }
        });
    }
}
_

スタートアップクラス:

_public void ConfigureServices(IServiceCollection services)
{
    services.AddMvc().SetCompatibilityVersion(CompatibilityVersion.Version_2_1);

    services.AddSignalR();
}

public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
    app.UseDeveloperExceptionPage();

    app.UseHttpsRedirection();

    app.UseSignalR((x) =>
    {
        x.MapHub<TimeHub>("/timeHub");
    });
    app.UseMvc();
}
_

クライアントはコンソールアプリケーションであり、コードは次のとおりです。

_class Program
{    
    static Action<string> OnReceivedAction = OnReceived;

    static void Main(string[] args)
    {
        Connect();
        Console.ReadLine();
    }

    private static async void Connect()
    {
        var hubConnectionBuilder = new HubConnectionBuilder();

        var hubConnection = hubConnectionBuilder.WithUrl("http://localhost:60211/timeHub").Build();

        await hubConnection.StartAsync();

        var on = hubConnection.On("ReceiveMessage", OnReceivedAction);

        Console.ReadLine();    
        on.Dispose();
        await hubConnection.StopAsync();
    }

    static void OnReceived(string message)
    {
        System.Console.WriteLine($"{message}");
    }
}
_

アプリケーションをデバッグしてみました。クライアントはTimeHubに正常に接続されました。クライアントが接続されると、_Clients.All_の接続数が0から1に変更されました。ただし、await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());が実行されると、UpdateTimeTimeHub関数は実行されず、クライアントはメッセージを受け取りません。

TimeRelayクラスの_"UpdateTime"_のメソッドとして、_"SendMessage"_、_"ReceiveMessage"_、および_Clients.All.SendAsync_を使用してみました。何も機能しませんでした。誰かがこれで私の間違いを指摘できますか?.

5
Alen Alex

私はそれを機能させ、ここで答えようと思いました。ヒントをありがとう@TaoZhou。

私の間違いは、サーバーから「UpdateTime」を送信し、クライアントで「ReceiveMessage」を待機することでした。

理想的には、コードは次のようになります。

SignalRサーバー:
await context.Clients.All.SendAsync("UpdateTime", DateTime.Now.ToShortDateString());

SignalRクライアント:
var on = hubConnection.On("UpdateTime", OnReceivedAction);

この場合、サーバーから送信されたメッセージはすべてクライアントで即座に受信されます。
詳細については、質問に記載されているコードを参照してください。

1
Alen Alex

Clientsの場合、サーバーに接続しているクライアントがない場合はnullになります。開始するためにAsp.Net Core SignalRおよびConsole App同時に、コンソールアプリがsignalRサーバーに接続する前にClientsが呼び出される可能性があるため、Indexがnullになる可能性があります。

以下の手順を試してください。

  1. TimeHubを変更します

    public class TimeHub: Hub
    {
    public async Task UpdateTime(string message)
    {
        if (Clients != null)
        {
            await Clients.All.SendAsync("ReceiveMessage", message);
        }
    }
    }
    
  2. 登録TimeHub

     services.AddSingleton<TimeHub>();  
    
  3. コントローラ

     public class HomeController : Controller
    {
    private readonly TimeHub _timeHub;
    public HomeController(TimeHub timeHub)
    {
        _timeHub = timeHub;
    }
    public IActionResult Index()
    {
        Task.Factory.StartNew(async () =>
        {
            while (true)
            {
                try
                {
                    await _timeHub.UpdateTime(DateTime.Now.ToShortDateString());
                    Thread.Sleep(2000);
                }
                catch (Exception ex)
                {
    
                }
            }
        });
        return View();
    }
    
1
Edward