【问题标题】:Updating a list with Signalr使用 Signalr 更新列表
【发布时间】:2015-01-05 19:12:00
【问题描述】:

我正在编写一个信号器客户端-服务器应用程序。

服务器维护一个项目列表。

客户端显示列表并让用户将项目添加到列表中。

假设服务器有一个返回整个列表的GetList 方法,客户端有一个NewItem 方法,当客户端向列表中添加项目时服务器调用。

这是客户端代码:

public void Init()
{
    hubConnection = new HubConnection(url);
    proxy = hubConnection.CreateHubProxy(hubName);
    proxy.On<String>("NewItem", OnNewItem);
    hubConnection.Start();
    list = proxy.Invoke("GetList");
}

private void OnNewItem(string item)
{
   list.Add(item);
}

我担心以下情况:

  1. 客户端 A 已连接
  2. 客户端 B 连接到服务器
  3. 客户端 A 将一个项目添加到列表中,同时客户端 B 发送 GetList 消息以获取列表

此时服务器中有2个线程。线程 A 正在添加一个项目,然后向客户端发送一个带有新项目的事件。线程 B 正在加载列表并将其发送回客户端 B。

假设线程 B 在线程 A 添加新项目之前从数据库中加载了列表。然后有一个上下文切换,线程 A 添加了该项目并向所有客户端发送了一条带有新项目的消息。

现在线程 B 恢复并将列表(不包括新项目)发送给客户端 B。

从客户 B 的角度来看,它得到了一个事件,其中包含他不知道如何处理的新项目,然后它得到了列表但没有新项目。

客户端 B 可以忽略新项目消息(因为它在列表初始化之前出现),但他总是会丢失 1 个项目,因为服务器永远不会为该项目发送另一个事件。

B 也可以将消息添加到空列表中,然后添加它获得的列表。但是如果客户 A 没有添加一个项目,而是删除了一个项目怎么办? B 在列表初始化之前如何处理删除项事件?

【问题讨论】:

  • 如果列表未初始化,为什么不能忽略消息(例如 proxy.On("NewItem", s => if(list != null){OnNewItem(s) ;});? For deletes you probably need something like OnDelete notification. On the other hand - you should await` 你的 StartInvoke 调用。最后你可能需要考虑线程 - 如果同时调用 OnNewItem 和 OnDelete 会发生什么?List 不是线程安全的。
  • @Pawel 我添加了一个可能在 2 个客户端和服务器之间发生的竞争条件的示例。

标签: c# signalr


【解决方案1】:

您尝试执行的操作听起来可能有些困难,尤其是当您允许多个客户端同时任意编辑列表时。如果是这种情况,您将考虑实施operational transformation algorithm。虽然这已经得到了相当广泛的研究,但它绝非微不足道。

如果您只是想订阅由单一来源所做的编辑,这将更容易处理。您可以利用这一事实,即您将订阅在await hubConnection.Start(); 完成后发送的任何更新。

这意味着,只要您正确地await,您的客户端OnNewItem 回调将接收在您的客户端调用“GetList”期间或之后对“NewItem”进行的任何服务器端调用在尝试调用“GetList”之前调用hubConnection.Start()

您在OnNewItem 中收到的项目仍可能与对“GetList”的响应重复。要解决此问题,您可以为添加到列表中的每个项目提供一个单调递增的 ID,并将其与项目本身一起传递给 OnNewItem 回调。 “GetList”响应还应包括其最近添加的项目的 ID。

在您收到对“GetList”的响应之前,您会将在OnNewItem 中收到的任何项目保存在一个临时列表中。一旦您收到对“GetList”的响应,您就可以在临时列表中添加 ID 大于添加到“GetList”响应中的最新项目的 ID 的任何项目。您忽略 ID 小于或等于“GetList”响应中返回的 ID 的任何项目。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2021-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-06-20
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多