From 8627ae61facb4201aaf40901bb34ca6295657cab Mon Sep 17 00:00:00 2001 From: xRain Date: Sat, 17 May 2025 21:11:27 +0800 Subject: [PATCH] use lock --- Synapse/RpcClient.cs | 100 ++++++++++++++++++++++--------------------- 1 file changed, 52 insertions(+), 48 deletions(-) diff --git a/Synapse/RpcClient.cs b/Synapse/RpcClient.cs index 85e5825..cb26c17 100644 --- a/Synapse/RpcClient.cs +++ b/Synapse/RpcClient.cs @@ -43,60 +43,64 @@ public partial class Synapse private string? FireRpc(string app, string action, object? param, Dictionary? headers = null, int? timeout = null) { - string paramJson; - if (param is string strParam) + // 检查并发情况下的线程安全问题,使用锁保证字典操作的原子性 + lock (ResponseCompletionSources) { - paramJson = strParam; - } - else - { - paramJson = JsonSerializer.Serialize(param, SimApiUtil.JsonOption); - } - - var topic = $"{Options.SysName}/{app}/rpc/server/{action}"; - var messageId = Guid.NewGuid().ToString(); - var tcs = new TaskCompletionSource(); - ResponseCompletionSources.Add(messageId, tcs); - var messageBuilder = new MqttApplicationMessageBuilder() - .WithTopic(topic) - .WithPayload(paramJson) - .WithResponseTopic($"{Options.AppName},{Options.AppId},{messageId}") - .WithContentType("application/json") - .WithRetainFlag(false); - foreach (var h in headers ?? new Dictionary()) - { - messageBuilder.WithUserProperty(h.Key, h.Value); - } - - var message = messageBuilder.Build(); - if (!Client!.IsConnected) return null; - Client.PublishAsync(message, CancellationToken.None).Wait(); - logger.LogDebug( - "Synapse RPC Client Request: ({PropsMessageId}) {OptionsAppName} -> {Action}@{App}\n{ParamJson}\nHeaders: {Headers}", - messageId, Options.AppName, action, app, paramJson, JsonSerializer.Serialize(headers)); - - string response; - try - { - timeout ??= Options.RpcTimeout; - if (tcs.Task.Wait(timeout.Value * 1000)) + string paramJson; + if (param is string strParam) { - response = tcs.Task.Result; - logger.LogDebug( - "Synapse RPC Client Response: ({BasicPropertiesCorrelationId}) {BasicPropertiesType}@{BasicPropertiesReplyTo} -> {OptionsAppName}\n{S}", - messageId, action, app, Options.AppName, response); + paramJson = strParam; } else { - response = JsonSerializer.Serialize(new SimApiBaseResponse(502, "timeout"), SimApiUtil.JsonOption); + paramJson = JsonSerializer.Serialize(param, SimApiUtil.JsonOption); } - } - catch - { - response = JsonSerializer.Serialize(new SimApiBaseResponse(500, "Synapse RPC Client Error"), - SimApiUtil.JsonOption); - } - return response; + var topic = $"{Options.SysName}/{app}/rpc/server/{action}"; + var messageId = Guid.NewGuid().ToString(); + var tcs = new TaskCompletionSource(); + ResponseCompletionSources.Add(messageId, tcs); + var messageBuilder = new MqttApplicationMessageBuilder() + .WithTopic(topic) + .WithPayload(paramJson) + .WithResponseTopic($"{Options.AppName},{Options.AppId},{messageId}") + .WithContentType("application/json") + .WithRetainFlag(false); + foreach (var h in headers ?? new Dictionary()) + { + messageBuilder.WithUserProperty(h.Key, h.Value); + } + + var message = messageBuilder.Build(); + if (!Client!.IsConnected) return null; + Client.PublishAsync(message, CancellationToken.None).Wait(); + logger.LogDebug( + "Synapse RPC Client Request: ({PropsMessageId}) {OptionsAppName} -> {Action}@{App}\n{ParamJson}\nHeaders: {Headers}", + messageId, Options.AppName, action, app, paramJson, JsonSerializer.Serialize(headers)); + + string response; + try + { + timeout ??= Options.RpcTimeout; + if (tcs.Task.Wait(timeout.Value * 1000)) + { + response = tcs.Task.Result; + logger.LogDebug( + "Synapse RPC Client Response: ({BasicPropertiesCorrelationId}) {BasicPropertiesType}@{BasicPropertiesReplyTo} -> {OptionsAppName}\n{S}", + messageId, action, app, Options.AppName, response); + } + else + { + response = JsonSerializer.Serialize(new SimApiBaseResponse(502, "timeout"), SimApiUtil.JsonOption); + } + } + catch + { + response = JsonSerializer.Serialize(new SimApiBaseResponse(500, "Synapse RPC Client Error"), + SimApiUtil.JsonOption); + } + + return response; + } } } \ No newline at end of file