SignalR:同步组加入

Posted

技术标签:

【中文标题】SignalR:同步组加入【英文标题】:SignalR: synchronizing group joining 【发布时间】:2013-03-11 10:05:09 【问题描述】:

我正在开发 android 应用程序并在我的 asp.net 服务器和自定义 java 客户端 SignalA 上使用 SignalR。我面临以下问题:当客户端加入某个组时,它没有收到加入后立即发送的消息。这是来自服务器的一段代码:

Task.Factory.StartNew(() => context.Groups.Add(groupId, connectionId)).
    ContinueWith(t => Groups.Send(groupId, message));

在客户端,我收到带有新组令牌的回调,但没有收到第一条发送的消息(但是收到了之后发送的消息)。用官方 C# 客户端尝试同样的事情效果很好。因此,似乎在处理新的组令牌之前收到了第一条消息。

经过长时间尝试比较 C# 和 java 客户端代码后,我没有找到解决方案。我正在寻找关于如何在 C# 客户端中处理这种情况的解释(或代码参考),以便能够在 java 客户端中实现相同的逻辑。

附:如果有办法将官方 C# 客户端与 android 一起使用,而不是使用自定义 java 客户端,那就更轻松了。

附言有一些“肮脏”的方法可以解决我的问题,比如加入群组后在服务器上稍作延迟或从客户端发送确认消息,但我仍在寻找“干净”的修复方法。

【问题讨论】:

【参考方案1】:

没有理由使用Task.Factory.StartNew

context.Groups.Add(connectionId, groupName) 已经返回您应该等待的Task,然后再向groupName 发送您期望由connectionId 标识的客户端的消息。

当你打电话时

Task.Factory.StartNew(() => context.Groups.Add(connectionId, groupName))

你会得到一个Task<Task>

这意味着当您在ContinueWith 内部调用Groups.Send(groupName, message) 时,只有外部Task 已完成,而connectionId 尚未完全添加到groupdName

如果您运行的是 .NET 4.5,重写此代码的最简单方法是使用 async/await 模式,如下所示:

public async Task AddToGroupAndSend(IPersistentConnectionContext context,
                                    string connectionId, 
                                    string groupName,
                                    object message)

    await context.Groups.Add(connectionId, groupName);
    await context.Groups.Send(groupName, message);

如果您运行的是 .NET 4.0,则可以继续使用 ContinueWith,但不使用 Task.Factory.StartNew

public Task AddToGroupAndSend(IPersistentConnectionContext context,
                              string connectionId, 
                              string groupName,
                              object message)

    // This doesn't appropriately handle faulted or canceled tasks
    return context.Groups.Add(connectionId, groupName)
                  .ContinueWith(t => groups.Send(groupName, message));

如果您不介意代码同步执行,您甚至可以执行以下操作:

public void AddToGroupAndSend(IPersistentConnectionContext context,
                              string connectionId, 
                              string groupName,
                              object message)

    context.Groups.Add(connectionId, groupName).Wait().
    groups.Send(groupName, message).Wait();

注意:在我的示例中,connectionIdcontext.Groups.Add 的第一个参数,groupName 是第二个参数。这是这些参数的正确顺序,与您在问题中的编写方式相反。

我不知道为什么您以前的代码可以与 C# 客户端一起使用,但不能与 Java 一起使用。鉴于您问题中提供的代码,我希望任何一个客户端都会错过第一条发送的消息。

【讨论】:

以上是关于SignalR:同步组加入的主要内容,如果未能解决你的问题,请参考以下文章

如何使用 SignalR 加入群组

SignalR 中的组是不是被归类为静态数据?

利用SignalR来同步更新Winfrom小试

建立连接时的 SignalR Core 调用函数

.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联

.net core 3.0 Signalr - 05 使用jwt将用户跟signalr关联