diff --git a/Realtime/Realtime/Internal/Connection/LCConnection.cs b/Realtime/Realtime/Internal/Connection/LCConnection.cs index c4703fa..1e7732a 100644 --- a/Realtime/Realtime/Internal/Connection/LCConnection.cs +++ b/Realtime/Realtime/Internal/Connection/LCConnection.cs @@ -1,4 +1,5 @@ using System; +using System.Linq; using System.Text; using System.Collections.Generic; using System.Threading.Tasks; @@ -12,6 +13,17 @@ namespace LeanCloud.Realtime.Internal.Connection { /// 连接层,只与数据协议相关 /// public class LCConnection { + // 请求/应答比对,即 I 相等 + class RequestAndResponseComparer : IEqualityComparer { + public bool Equals(GenericCommand x, GenericCommand y) { + return true; + } + + public int GetHashCode(GenericCommand obj) { + return obj.I; + } + } + /// /// 连接状态 /// @@ -59,8 +71,7 @@ namespace LeanCloud.Realtime.Internal.Connection { /// /// 请求回调缓存 /// - private readonly Dictionary> responses; - private readonly List sendingRequests; + private readonly Dictionary> requestToResponses; private int requestI = 1; @@ -79,8 +90,8 @@ namespace LeanCloud.Realtime.Internal.Connection { internal LCConnection(string id) { this.id = id; - responses = new Dictionary>(); - sendingRequests = new List(); + requestToResponses = new Dictionary>(new RequestAndResponseComparer()); + heartBeat = new LCHeartBeat(this, OnDisconnect); router = new LCRTMRouter(); ws = new LCWebSocketClient { @@ -130,25 +141,23 @@ namespace LeanCloud.Realtime.Internal.Connection { /// internal async Task SendRequest(GenericCommand request) { if (IsIdempotentCommand(request)) { - GenericCommand sendingReq = sendingRequests.Find(item => { + GenericCommand sendingReq = requestToResponses.Keys.FirstOrDefault(item => { // TRICK 除了 I 其他字段相等 request.I = item.I; return Equals(request, item); }); if (sendingReq != null) { LCLogger.Warn("duplicated request"); - if (responses.TryGetValue(sendingReq.I, out TaskCompletionSource waitingTcs)) { + if (requestToResponses.TryGetValue(sendingReq, out TaskCompletionSource waitingTcs)) { return await waitingTcs.Task; } LCLogger.Error($"error request: {request}"); - } else { - sendingRequests.Add(request); } } TaskCompletionSource tcs = new TaskCompletionSource(); request.I = requestI++; - responses.Add(request.I, tcs); + requestToResponses.Add(request, tcs); try { await SendCommand(request); } catch (Exception e) { @@ -196,7 +205,7 @@ namespace LeanCloud.Realtime.Internal.Connection { if (command.HasI) { // 应答 int requestIndex = command.I; - if (responses.TryGetValue(requestIndex, out TaskCompletionSource tcs)) { + if (requestToResponses.TryGetValue(command, out TaskCompletionSource tcs)) { if (command.HasErrorMessage) { // 错误 ErrorCommand error = command.ErrorMessage; @@ -206,12 +215,9 @@ namespace LeanCloud.Realtime.Internal.Connection { LCException exception = new LCException(code, detail); tcs.TrySetException(exception); } else { - sendingRequests.RemoveAll(item => { - return item.I == command.I; - }); tcs.TrySetResult(command); } - responses.Remove(requestIndex); + requestToResponses.Remove(command); } else { LCLogger.Error($"No request for {requestIndex}"); }