SignalR:同步组加入

Yur*_*yak 0 asp.net signalr

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

Task.Factory.StartNew(() => context.Groups.Add(groupId, connectionId)).
    ContinueWith(t => Groups.Send(groupId, message));
Run Code Online (Sandbox Code Playgroud)

在客户端,我收到一个带有新组令牌的回调,但是没有收到第一个发送的消息(但是接收到后来发送的消息).与官方C#客户端尝试相同的工作非常有效.因此,似乎在处理新组令牌之前收到第一条消息.

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

PS如果有一种方法可以使用官方的C#客户端而不是使用自定义的Java客户端,那么它会更加轻松.

PPS有一些"脏"方法来解决我的问题,比如在加入群组或从客户端发送确认消息后在服务器上稍微延迟,但我仍然在寻找"干净"修复.

hal*_*r73 5

没有理由使用Task.Factory.StartNew.

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

你打电话的时候

Task.Factory.StartNew(() => context.Groups.Add(connectionId, groupName))
Run Code Online (Sandbox Code Playgroud)

你得到一个Task<Task>.

这意味着当您Groups.Send(groupName, message)在内部调用时ContinueWith,只有外部任务已完成,并且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);
}
Run Code Online (Sandbox Code Playgroud)

如果您运行的是.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));
}
Run Code Online (Sandbox Code Playgroud)

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

public void AddToGroupAndSend(IPersistentConnectionContext context,
                              string connectionId, 
                              string groupName,
                              object message)
{
    context.Groups.Add(connectionId, groupName).Wait().
    groups.Send(groupName, message).Wait();
}
Run Code Online (Sandbox Code Playgroud)

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

我不知道为什么你以前的代码可以使用C#客户端而不能使用Java.鉴于您的问题中提供的代码,我希望客户端错过第一个发送的消息.