From 249b0f9fbb47be876999f81c2c16ed31a61f6424 Mon Sep 17 00:00:00 2001 From: Viacheslav Demydiuk Date: Fri, 5 Dec 2025 23:43:27 +0200 Subject: [PATCH] Issue #262: function GetQuotes load data from MT instead of using cached quotes --- MtApi5/MtApi5Client.cs | 50 ++++++++++++-------- MtClient/MtMessage.cs | 14 +++--- MtClient/MtRpcClient.cs | 22 ++++----- MtService/MtMessage.cpp | 12 ++--- MtService/MtMessage.h | 22 ++++----- MtService/MtServer.cpp | 10 ++-- TestClients/MtApi5TestClient/MainWindow.xaml | 2 + TestClients/MtApi5TestClient/ViewModel.cs | 16 +++++++ 8 files changed, 88 insertions(+), 60 deletions(-) diff --git a/MtApi5/MtApi5Client.cs b/MtApi5/MtApi5Client.cs index 6a2e5cab..a80ffd57 100755 --- a/MtApi5/MtApi5Client.cs +++ b/MtApi5/MtApi5Client.cs @@ -123,14 +123,7 @@ namespace MtApi5 throw new Exception($"Connection to {host}:{port} failed. Error: {errorMessage}"); } - // Load quotes - Dictionary quotes = []; - foreach (var handle in experts) - { - var quote = GetQuote(client, handle); - if (quote != null) - quotes[handle] = quote; - } + var quotes = LoadQuotes(client, experts); lock (_locker) { @@ -160,6 +153,18 @@ namespace MtApi5 } } + private Dictionary LoadQuotes(MtRpcClient client, HashSet experts) + { + Dictionary quotes = []; + foreach (var handle in experts) + { + var quote = GetQuote(client, handle); + if (quote != null) + quotes[handle] = quote; + } + return quotes; + } + /// ///Disconnect from MetaTrader API. Async method. /// @@ -183,10 +188,22 @@ namespace MtApi5 /// public IEnumerable GetQuotes() { + MtRpcClient? client; + HashSet experts; lock (_locker) { - return _quotes.Values.ToList(); + client = _client; + experts = new HashSet(_experts); } + if (client == null) + { + Log.Warn("GetQuotes: No connection"); + throw new Exception("No connection"); + } + + var quotes = LoadQuotes(client, experts); + + return quotes.Values.ToList(); } /// @@ -3402,11 +3419,6 @@ namespace MtApi5 var quote = GetQuote(Client, handle); if (quote != null) { - lock (_locker) - { - _quotes[handle] = quote; - } - QuoteAdded?.Invoke(this, new Mt5QuoteEventArgs(quote)); } else @@ -3421,19 +3433,18 @@ namespace MtApi5 { Log.Debug($"ProcessExpertRemoved: {handle}"); - Mt5Quote? quote = null; + Mt5Quote? quote; lock (_locker) { + _quotes.TryGetValue(handle, out quote); + _quotes.Remove(handle); _experts.Remove(handle); - if (_quotes.TryGetValue(handle, out quote)) - _quotes.Remove(handle); if (_executorHandle == handle) _executorHandle = (_experts.Count > 0) ? _experts.ElementAt(0) : 0; - } if (quote != null) - QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(quote)); + QuoteRemoved?.Invoke(this, new Mt5QuoteEventArgs(new Mt5Quote { Instrument = quote.Instrument, ExpertHandle = quote.ExpertHandle })); } private Mt5Quote? GetQuote(MtRpcClient? client, int expertHandle) @@ -3550,7 +3561,6 @@ namespace MtApi5 client = _client; _client = null; - _quotes.Clear(); _experts.Clear(); _executorHandle = 0; } diff --git a/MtClient/MtMessage.cs b/MtClient/MtMessage.cs index 4618edfa..777c29ec 100755 --- a/MtClient/MtMessage.cs +++ b/MtClient/MtMessage.cs @@ -8,12 +8,12 @@ ExpertList = 3, ExpertAdded = 4, ExpertRemoved = 5, - Notification = 6 + ServiceRequest = 6 } - internal enum MtNotificationType + internal enum ServiceRequestType { - ClientReady = 0 + ExpertList = 0 } internal abstract class MtMessage @@ -43,16 +43,16 @@ } } - internal class MtNotification(MtNotificationType notificationType) : MtMessage + internal class MtServiceRequest(ServiceRequestType requestType) : MtMessage { - public override MessageType MsgType => MessageType.Notification; + public override MessageType MsgType => MessageType.ServiceRequest; protected override string GetMessageBody() { - return $"{(int)NotificationType}"; + return $"{(int)ServiceRequestType}"; } - public MtNotificationType NotificationType { private set; get; } = notificationType; + public ServiceRequestType ServiceRequestType { private set; get; } = requestType; } internal class MtEvent(int expertHandle, int eventType, string payload) : MtMessage diff --git a/MtClient/MtRpcClient.cs b/MtClient/MtRpcClient.cs index 48d06dd0..c1fbbeeb 100755 --- a/MtClient/MtRpcClient.cs +++ b/MtClient/MtRpcClient.cs @@ -89,19 +89,19 @@ namespace MtClient public HashSet? RequestExpertsList() { - CommandTask notificationTask = new(); - lock (notification_tasks_) + CommandTask requestTask = new(); + lock (service_requests_) { - notification_tasks_[MtNotificationType.ClientReady] = notificationTask; + service_requests_[ServiceRequestType.ExpertList] = requestTask; } - MtNotification notification = new(MtNotificationType.ClientReady); - Send(notification); + MtServiceRequest request = new(ServiceRequestType.ExpertList); + Send(request); - var response = notificationTask.WaitResponse(10000); // 10 sec - lock (notification_tasks_) + var response = requestTask.WaitResponse(10000); // 10 sec + lock (service_requests_) { - notification_tasks_.Remove(MtNotificationType.ClientReady); + service_requests_.Remove(ServiceRequestType.ExpertList); } return response as HashSet; @@ -277,9 +277,9 @@ namespace MtClient { logger_.Debug($"MtRpcClient.ProcessExpertList: experts count - {experts.Count}"); - lock (notification_tasks_) + lock (service_requests_) { - if (notification_tasks_.TryGetValue(MtNotificationType.ClientReady, out CommandTask? value)) + if (service_requests_.TryGetValue(ServiceRequestType.ExpertList, out CommandTask? value)) value.SetResponse(experts); } } @@ -301,7 +301,7 @@ namespace MtClient private int nextCommandId = 0; private readonly Dictionary> tasks_ = []; - private readonly Dictionary> notification_tasks_ = []; + private readonly Dictionary> service_requests_ = []; private readonly IRpcLogger logger_; } diff --git a/MtService/MtMessage.cpp b/MtService/MtMessage.cpp index 712b3720..27c9b2f4 100755 --- a/MtService/MtMessage.cpp +++ b/MtService/MtMessage.cpp @@ -38,7 +38,7 @@ std::unique_ptr MtCommand::Parse(const std::string& msg) return command; } -std::unique_ptr MtNotification::Parse(const std::string& msg) +std::unique_ptr MtServiceRequest::Parse(const std::string& msg) { std::string::size_type pos = msg.find(';'); @@ -47,17 +47,17 @@ std::unique_ptr MtNotification::Parse(const std::string& msg) using rule = qi::rule; std::string message_type; - std::string notification_type; + std::string request_type; rule_s word_p = qi::as_string[+(qi::char_ - qi::char_(';'))]; rule message_type_p = word_p[boost::phoenix::ref(message_type) = qi::_1]; - rule notification_type_p = +qi::char_(';') >> word_p[boost::phoenix::ref(notification_type) = qi::_1]; + rule notification_type_p = +qi::char_(';') >> word_p[boost::phoenix::ref(request_type) = qi::_1]; - std::unique_ptr command; + std::unique_ptr request; bool ok = qi::parse(msg.begin(), msg.end(), message_type_p >> -notification_type_p); if (ok) - command = std::make_unique((NotificationType)std::stoi(notification_type)); + request = std::make_unique((ServiceRequestType)std::stoi(request_type)); - return command; + return request; } \ No newline at end of file diff --git a/MtService/MtMessage.h b/MtService/MtMessage.h index 3152ed28..33fcd8ca 100755 --- a/MtService/MtMessage.h +++ b/MtService/MtMessage.h @@ -14,12 +14,12 @@ enum MessageType EXPERT_LIST = 3, EXPERT_ADDED = 4, EXPERT_REMOVED = 5, - NOTIFICATION = 6 + SERVICE_REQUEST = 6 }; -enum NotificationType +enum ServiceRequestType { - CLIENT_READY = 0 + EXPERTS = 0 }; class MtMessage @@ -111,25 +111,25 @@ private: std::string payload_; }; -class MtNotification : public MtMessage +class MtServiceRequest : public MtMessage { public: - MtNotification(NotificationType type) - : notification_type_(type) + MtServiceRequest(ServiceRequestType type) + : request_type_(type) { } - NotificationType GetNotificationType() const + ServiceRequestType GetServiceRequestType() const { - return notification_type_; + return request_type_; } - static std::unique_ptr Parse(const std::string& msg); + static std::unique_ptr Parse(const std::string& msg); private: MessageType GetType() const override { - return MessageType::NOTIFICATION; + return MessageType::SERVICE_REQUEST; } std::string GetBody() const override @@ -137,7 +137,7 @@ private: return ""; } - NotificationType notification_type_; + ServiceRequestType request_type_; }; class MtEvent : public MtMessage diff --git a/MtService/MtServer.cpp b/MtService/MtServer.cpp index 90813134..bfec5c13 100755 --- a/MtService/MtServer.cpp +++ b/MtService/MtServer.cpp @@ -288,12 +288,12 @@ void MtServer::ProcessMessage(const std::string& msg, std::weak_ptrGetNotificationType() == NotificationType::CLIENT_READY) + if (request->GetServiceRequestType() == ServiceRequestType::EXPERTS) { std::vector expert_list; for (const auto& e : experts_) @@ -306,7 +306,7 @@ void MtServer::ProcessMessage(const std::string& msg, std::weak_ptr +