如何解决使用不同线程中提供的 IHubContext 与 SingalR 客户端连接
我正在使用 ASP.NET Core,并且我正在通过 SingalR 集线器端点将一些用户添加到集合中:
#include <iostream>
struct Foo
{
int& something;
int& something_else;
};
void foo(const Foo& f)
{
f.something = 1;
f.something_else = 2;
}
int main() {
int x,y;
foo({x,y});
std::cout << x << " " << y; // Output is 1 and 2.
}
public class MatchMakingHub : Hub
{
//....
// called by client
public async Task EnlistMatchMaking(int timeControlMs)
{
Guid currentId = Guid.Parse(this.Context.User.GetSubjectId());
GetPlayerByIdQuery getPlayerByIdQuery = new GetPlayerByIdQuery(currentId);
Player currentPlayer = await requestSender.Send<Player>(getPlayerByIdQuery);
var waitingPlayer = new WaitingPlayer(currentPlayer,timeControlMs);
this.matchMakePool.Add(waitingPlayer);
}
}
是一个单例集合。
后来,我有一个 ASP.NET Core 后台服务从集合中获取用户,并通知他们被获取:
matchMakePool
我的问题是客户端没有调用 public class MatchMakingBackgroundService : BackgroundService
{
private readonly MatchMakePoolSingleton matchMakePoolSingleton;
private readonly IServiceProvider serviceProvider;
private const int RefreshTimeMs = 1000;
public MatchMakingBackgroundService(MatchMakePoolSingleton matchMakePoolSingleton,IServiceProvider serviceProvider)
{
this.matchMakePoolSingleton = matchMakePoolSingleton;
this.serviceProvider = serviceProvider;
}
protected override async Task ExecuteAsync(CancellationToken stoppingToken)
{
while(!stoppingToken.IsCancellationRequested)
{
var result = matchMakePoolSingleton.RefreshMatches();
var tasks = new List<Task>();
foreach(var match in result)
{
tasks.Add(StartGameAsync(match));
}
await Task.WhenAll(tasks);
await Task.Delay(RefreshTimeMs,stoppingToken);
}
}
private async Task StartGameAsync(MatchMakeResult match)
{
using var scope = serviceProvider.CreateScope();
var sender = scope.ServiceProvider.GetrequiredService<ISender>();
var hubContext = serviceProvider.GetrequiredService<IHubContext<MatchMakingHub>>();
CreateNewGameCommand newGameCommand = new CreateNewGameCommand(match.WhitePlayer.Id,match.BlackPlayer.Id,TimeSpan.FromMilliseconds(match.TimeControlMs));
Guid gameGuid = await sender.Send(newGameCommand);
await hubContext.Clients.User(match.WhitePlayer.Id.ToString()).SendAsync("NotifyGameFound",gameGuid);
await hubContext.Clients.User(match.BlackPlayer.Id.ToString()).SendAsync("NotifyGameFound",gameGuid);
}
}
。当我直接从集线器本身通知他们时,它已收到,但由于某种原因,当我通过提供的 NotifyGameFound
调用它时却没有。我怀疑这是因为它在另一个线程上运行。
这是客户端代码:
IHubContext<MatchMakingHub>
解决方法
我使用注入来实现这一点。
在我的服务器 Startup.cs
ConfigureServices
中我有:
services.AddScoped<INotificationsBroker,NotificationsBroker>();
在您的情况下,我假设您正在注入 MatchMakingBackgroundService
类似的东西:
services.AddScoped<MatchMakingBackgroundService>();
在我的 NotificationsBroker
构造函数中,我注入了上下文:
private readonly IHubContext<NotificationsHub> hub;
public NotificationsBroker(IHubContext<NotificationsHub> hub)
=> this.hub = hub;
然后我将代理注入到我需要的任何服务中,该服务可以调用我通过接口公开的集线器方法。
您不必执行额外的步骤,我这样做是为了测试,您可以将上下文直接注入您的 MatchMakingBackgroundService
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。