用OpenQQ实现独占式编辑
本节讲述如何避免多人同时编辑同一行,既如何实现独占式编辑。
利用OpenQQ,可以很轻松实现此功能。
要实现此功能,服务器端和客户端都要进行相应的设计,我们学习的时候,也要结合客户端和服务端的代码来理解。
一。服务器端的设计
1、在服务器端项目的全局代码中,加入如下代码:
Public tbrk As new Dictionary(of String,String)
tbrk是一个字典,用于登记每一行是谁在编辑。
我们约定接下来编码的时候:字典的键由表名和行的主键组合成,值则等于编辑者名。
2、在服务端项目的OpenQQ服务端的ReceivedMessage事件加上代码:
Dim msg As String = e.Message
If msg.StartsWith("?#") AndAlso msg.EndsWith("#?") Then '收到请求编辑信号
Dim Key As String = msg.SubString(2,msg.Length - 4)
If tbrk.Containskey(Key) = False Then '如果无人编辑此行
tbrk.Add(Key,e.UserName) '登记申请者为此行的编辑者
e.ReturnValue = "OK" '通知申请者可以编辑
ElseIf tbrk(Key) = e.UserName Then '如果申请者就是之前登记的编辑者
e.ReturnValue = "OK" '通知申请者可以编辑
Else '如果之前登记的编辑者为其他人
e.ReturnValue = tbrk(Key) & "正在编辑此行!" '告知申请者是谁在编辑此行
End If
ElseIf msg.StartsWith("!#") AndAlso msg.EndsWith("#!") Then '收到结束编辑信号
Dim Key As String = msg.SubString(2,msg.Length - 4)
If tbrk.Containskey(Key) Then
tbrk.Remove(Key) '从集合中移除此行的编辑登记
End If
End If
上述代码的注释详尽明了,就不做解释了。
3、在服务端项目的OpenQQ服务端的UserLogout事件加上代码:
Dim Keys As New List(of String)
For Each Key As String In tbrk.Keys
If tbrk(Key) = e.UserName Then
Keys.Add(Key)
End If
Next
For Each Key As String In Keys
tbrk.Remove(Key)
Next
这样当有用户退出登录时,不管他是正常退出还是异常退出,都可以将字典中该用户的编辑登记移除,避免死锁。
客户端用户异常退出时,服务端的编辑登记的移除会有一个延时,时长取决于QQServer的HeartbeatTimeout(心跳超时)属性。
上述编码有一个地方需要注意,我们不能在遍历字典或集合的过程中移除其成员(运行时会报错),所以我们用一个临时的集合Keys,先将要移除的键值保存在这个集合中,最后遍历这个集合中的键值,从字典tbrk中移除这些键值。
二。如果是窗口编辑
上述方案针对的是直接在表中编辑数据,如果不是在表中编辑,而是在窗口编辑,编码方式也是基本相同的。
通常只需将打开编辑窗口的代码改为:
Dim r As Row = Tables("表B").Current
If QQClient.Ready = False Then '如果QQClient没有启动,则禁止编辑
PopMessage("必须启动QQClient,才能编辑此表数据!","提示",PopIconEnum.Infomation,5)
Return
End If
If r.DataRow.RowState <> DataRowState.Added Then '如果不是新增行
Dim key As String = "表B" & ":" & r("_Identify")
If tbrk.Contains(key) = False Then
Dim msg = QQClient.SendWait("?#" & Key & "#?",5) '向服务器发送请求编辑信息
If msg = "OK" Then '如果服务器返回OK
tbrk.Add(key) '在本地登记正在编辑此行
ElseIf msg > "" Then '否则显示服务器返回的信息,并取消编辑
PopMessage("无法编辑此行,因为:" & vbcrlf & msg ,"提示",PopIconEnum.Infomation,5)
Return
Else '如果服务器没有返回信息,则取消编辑
PopMessage("因服务器无响应,无法编辑此行!" ,"提示",PopIconEnum.Infomation,5)
Return
End If
End If
End If
Forms("编辑窗口").Open()
问题2:1、在服务器端项目的全局代码中,加入如下代码:
Public tbrk As new Dictionary(of String,String)
服务器端项目的全局,在哪里?“网络监测器”里没看到,项目事件倒是有全局?
此主题相关图片如下:服务器.jpg