WPF中Websocket消息优化

前言

在用WS做一些互动的逻辑时,我们一般会在下面的方法中做业务逻辑

1
2
3
4
5
private void NewMessageReceived(WebSocketSession session, string message)
{
ZWsMsgVo msgBean = ZJsonHelper.JsonToObj<ZWsMsgVo>(message);
//其他逻辑
}

但是消息的接收是多线程的,那么会出现这么一个情况,如果消息的处理必须有先后的话,处理的时候就会出问题,比如一个是上线信息,一个是下线信息,一个是给上线用户发的信息,

如果我们想要的执行的顺序是处理上线信息=>给上线用户发消息=>处理用户下线信息,

但是可能执行时处理上线信息=>处理用户下线信息=>给上线用户发消息,这样就没法给该用户发消息了,所以我们要把用户上下线和其他消息放在一个队列中,让用户上下线信息串行执行,而其他信息并行执行

先定义实体类

1
2
3
4
5
6
7
8
9
10
using SuperWebSocket;

namespace SchoolClient.Socket
{
public class ZWSMessageModel
{
public WebSocketSession session { set; get; }
public string message { set; get; }
}
}

定义队列

1
2
3
4
//接收的消息队列
private static readonly Queue<ZWSMessageModel> receiveMsgQueue = new Queue<ZWSMessageModel>();
//是否正在处理队列
private bool isHandleQueue = false;

消息处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
private void NewMessageReceived(WebSocketSession session, string message)
{
Console.WriteLine("WS:接收" + message);
receiveMsgQueue.Enqueue(
new ZWSMessageModel()
{
session = session,
message = message
}
);

//保证同时只有一个线程在处理消息
if (!isHandleQueue)
{
handleMessageQueue();
}
}

private void handleMessageQueue()
{
isHandleQueue = true;
while (receiveMsgQueue.Count > 0)
{
ZWSMessageModel item = receiveMsgQueue.Dequeue();
string message = item.message;
WebSocketSession session = item.session;
try
{
ZWsMsgVo msgBean = ZJsonHelper.JsonToObj<ZWsMsgVo>(message);
if (msgBean.type == 101 || msgBean.type == 102)
{
//上下线信息单线程处理
handleMessageSingle(session, msgBean);
}
else
{
//其他信息多线程处理
ThreadPool.QueueUserWorkItem(
state =>
{
handleMessageSingle(session, msgBean);
}
);
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}

isHandleQueue = false;
}

private void handleMessageSingle(WebSocketSession session, ZWsMsgVo msgBean)
{
////其他逻辑
}

这样就可以保证处理消息的先后了。