我正在开发Android应用并在我的SignalR
服务器和自定义Java客户端SignalA上使用asp.net
。我遇到以下问题:当客户端加入某个组时,它不会收到加入后立即发送的消息。这是来自服务器的一段代码:
Task.Factory.StartNew(() => context.Groups.Add(groupId, connectionId)).
ContinueWith(t => Groups.Send(groupId, message));
在客户端,我收到带有新组令牌的回调,但是没有收到第一个发送的消息(但是接收到之后发送的消息)。与官方C#客户端尝试相同的工作非常有效。因此,似乎在处理新的组令牌之前收到了第一条消息。
经过长时间尝试比较C#和java客户端代码我还没有找到解决方案。我正在寻找关于如何在C#客户端中处理这种情况的解释(或代码参考),以便我能够在java客户端中实现相同的逻辑。
P.S。如果有一种方法可以使用官方的C#客户端而不是使用自定义的Java客户端,那就更加轻松了。
P.P.S。有一些“脏”的方法可以解决我的问题,例如在加入群组或从客户端发送确认消息后在服务器上稍微延迟,但我仍然在寻找“干净”的解决方案。
答案 0 :(得分:5)
没有理由使用Task.Factory.StartNew
。
context.Groups.Add(connectionId, groupName)
已经返回您应该等待的Task
,然后向groupName
发送一条消息,指出您希望connectionId
标识的客户端。
致电时
Task.Factory.StartNew(() => context.Groups.Add(connectionId, groupName))
你得到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);
}
如果您运行的是.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();
}
注意:在我的示例中,connectionId
是context.Groups.Add
的第一个参数,groupName
是第二个参数。这是这些参数的正确顺序,与您在问题中的编写方式相反。
我不知道为什么你以前的代码可以使用C#客户端而不能使用Java。鉴于您的问题中提供的代码,我希望任何一个客户端都会错过第一个发送的消息。