【发布时间】: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);
}
我担心以下情况:
- 客户端 A 已连接
- 客户端 B 连接到服务器
- 客户端 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 shouldawait` 你的Start和Invoke调用。最后你可能需要考虑线程 - 如果同时调用 OnNewItem 和 OnDelete 会发生什么?List不是线程安全的。 -
@Pawel 我添加了一个可能在 2 个客户端和服务器之间发生的竞争条件的示例。