Open cia76 opened 6 years ago
Добрый день. Можно ли вас попросить сбросить мне вашу программу на почту vdemydiuk@gmail.com? Я проверю ее у себя.
Похоже, ошибка происходит только тогда, когда идет обращение из разных потоков. Я запускаю один поток вначале для получения исторических данных. Затем запускаю таймер раз в 5 секунд для проверки заявок и позиций. Раз в минуту запускается поток обновления исторических данных. Когда каждый поток первый раз обращается к статичному свойству MtApiClient, то получаю ошибку.
Попробую сделать тестовый код, который воспроизводит ошибку. Весь проект слишком сложный, да и не нужен он весь.
Вообще-то нет смысла проверять состояние коннекта по таймеру. Для этого есть ивент ConnectionStateChanged который отлично подходить для этого и выдает нотификации, если состояние поменяется. Попробуйте использовать его.
Это понятно. Интересует не состояние соединения, а новые заявки, которые появились за последние 5 секунд. Как я понимаю, в MT4 события постановки заявки/позиции нет.
Все верно, таких событий нет. Но есть уже готовая реализация TradeMonitor (TimerTradeMonitor, TimeframeTradeMonitor), который выдает ивенты по закрытым и открытим ордерам. Возможно это то, что вам нужно.
Продолжаю отладку. Перед тем как получаю ошибку, то вижу, что ((System.ServiceModel.ClientBase
channel при этом существует. Вопрос становится таким: При каких обстоятельствах происходит разрыв соединения? Чтобы статус сменился с Open на Close нужно принудительно закрыть канал методом Close();
Пройдя по исходникам, я не нашел ситуаций принудительного разрыва соединения.
Это очень странная ситуация, когда канал произвольно закрывается. Мне нужно исходники примера с данной проблемой, чтобы воспроизвести ее локально и попробовать определить ее характер.
Возвращаясь к исходному коду:
/// <exception cref="CommunicationException">Thrown when connection failed</exception>
public MtResponse SendCommand(int commandType, ArrayList parameters, Dictionary<string, object> namedParams, int expertHandle)
{
Log.DebugFormat("SendCommand: begin. commandType = {0}, parameters count = {1}", commandType, parameters?.Count);
if (IsConnected == false)
{
Log.Error("SendCommand: Client is not connected.");
throw new CommunicationException("Client is not connected.");
}
Зачем выполняется проверка ISconnected? В каком случае может быть ситуация, когда прокси не подключен?
Насчет кода. Если я упрощаю код и вывожу код из своего проекта, то он работает ОК. Поэтому, я постепенно усложняю тестовый вариант до тех пор, пока не поймаю ошибку.
Проверка выполняется лишь с той целью, что пользователь может случайно сделать вызов функции API без подключения. При всегда правильном вызове функций это проверка немного избыточна.
Добрый день! Извиняюсь за запоздалый ответ. Если работать с MTApi из нескольких потоков одновременно, то канал, действительно, закрывается через произвольное время. Пришлось решать задачу через управление потоками. Чтобы в текущий момент времени только 1 поток мог работать с MTApi. После этого, описанная мною ошибка, исчезла. Если появится снова, то отпишусь в этой ветке. Благодарю за MTApi!
Все-таки, ошибка есть. Работаю в одном Task для получения котировок. Пример кода:
private static readonly ILog Logger = LogManager.GetLogger(typeof(MTWrapper));
private static readonly MtApiClient MTApiClient = new MtApiClient();
internal TimeArrayResult Time(string Symbol, ChartPeriod ChartPeriod)
{
var result = new TimeArrayResult();
lock (MTApiClient)
{
result.Value = MTApiClient.iTimeArray(Symbol, ChartPeriod);
result.ErrorId = MTApiClient.GetLastError();
result.ErrorDescription = MTApiClient.ErrorDescription(result.ErrorId);
}
Logger.Debug($"Time {Symbol} {ChartPeriod} Кол-во бар: {result.Value.Length}");
if (result.ErrorId != 0)
Logger.Error($"Ошибка Time {result.ErrorId} - {result.ErrorDescription}");
return result;
}
Я получаю эти данные в Task раз в 4 часа. Сначала при вызове
result.Value = MTApiClient.iTimeArray(Symbol, ChartPeriod);
новый бар не получаю, но ошибки нет. Такое может быть, т.к. часы на компьютере и в терминале MT4 не синхронизированы. Часы на компьютере чуть спешат. Чтобы получить новый бар, через 10 секунд повторно делаю тот же самый вызов. Получаю:
MtApi.MtConnectionException: Client is not connected. ---> System.ServiceModel.CommunicationException: Client is not connected.
в MTApiService.MtClient.SendCommand(Int32 commandType, ArrayList parameters, Dictionary2 namedParams, Int32 expertHandle) в MtApi.MtApiClient.SendCommand[T](MtCommandType commandType, ArrayList commandParameters, Dictionary
2 namedParams)
Ошибка происходит на разных компьютерах под Windows 10 со всеми установленными обновлениями.
Буду пробовать воспроизвести эту проблему со своей стороны. Надеюсь получиться в скором времени ее пофиксить.
Погонял код прошлую неделю. Если через интервалы от 1 минуты до 1 часа вызывать OrdersTotal и пр. методы работы с заявками, то все ОК.
internal int OrdersTotal
{
get
{
int result;
lock (MTApiClient)
{
result = MTApiClient.OrdersTotal();
Logger.Debug($"Активных заявок {result}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка OrdersTotal {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
}
Когда первый раз вызываю запрос Time/Open/High/Low/Close/Volume, то все также ОК
internal class MTWrapper
{
private static readonly ILog Logger = LogManager.GetLogger(typeof(MTWrapper));
private static readonly MtApiClient MTApiClient = new MtApiClient();
internal DateTime[] Time(string Symbol, ChartPeriod ChartPeriod)
{
DateTime[] result;
lock (MTApiClient)
{
result = MTApiClient.iTimeArray(Symbol, ChartPeriod);
Logger.Debug($"Time {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка Time {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
internal double[] Open(string Symbol, ChartPeriod ChartPeriod)
{
double[] result;
lock (MTApiClient)
{
result = MTApiClient.iOpenArray(Symbol, ChartPeriod);
Logger.Debug($"Open {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка Open {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
internal double[] High(string Symbol, ChartPeriod ChartPeriod)
{
double[] result;
lock (MTApiClient)
{
result = MTApiClient.iHighArray(Symbol, ChartPeriod);
Logger.Debug($"High {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка High {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
internal double[] Low(string Symbol, ChartPeriod ChartPeriod)
{
double[] result;
lock (MTApiClient)
{
result = MTApiClient.iLowArray(Symbol, ChartPeriod);
Logger.Debug($"Low {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка Low {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
internal double[] Close(string Symbol, ChartPeriod ChartPeriod)
{
double[] result;
lock (MTApiClient)
{
result = MTApiClient.iCloseArray(Symbol, ChartPeriod);
Logger.Debug($"Close {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка Close {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
internal double[] Volume(string Symbol, ChartPeriod ChartPeriod)
{
double[] result;
lock (MTApiClient)
{
result = MTApiClient.iVolumeArray(Symbol, ChartPeriod);
Logger.Debug($"Volume {Symbol} {ChartPeriod} Кол-во бар: {result.Length}");
int errorId = MTApiClient.GetLastError();
if (errorId != 0)
Logger.Error($"Ошибка Volume {errorId} - {MTApiClient.ErrorDescription(errorId)}");
}
return result;
}
}
Вызовы идут из Task вот так:
private readonly MTWrapper _mtWrapper = new MTWrapper(); // Обертка для связи с терминалом MT4
time = _mtWrapper.Time(Symbol, chartPeriod); open = _mtWrapper.Open(Symbol, chartPeriod); high = _mtWrapper.High(Symbol, chartPeriod); low = _mtWrapper.Low(Symbol, chartPeriod); close = _mtWrapper.Close(Symbol, chartPeriod); volume = _mtWrapper.Volume(Symbol, chartPeriod);
После этих вызовов любой другой вызов через любое время ведет к ошибке:
MtApi.MtConnectionException: Client is not connected. ---> System.ServiceModel.CommunicationException: Client is not connected.
в MTApiService.MtClient.SendCommand(Int32 commandType, ArrayList parameters, Dictionary2 namedParams, Int32 expertHandle) в MtApi.MtApiClient.SendCommand[T](MtCommandType commandType, ArrayList commandParameters, Dictionary
2 namedParams)
--- Конец трассировки внутреннего стека исключений ---
в MtApi.MtApiClient.SendCommand[T](MtCommandType commandType, ArrayList commandParameters, Dictionary`2 namedParams)
Вячеслав, мне отписался наш трейдер. У него возникает та же самая ошибка. Может, сделаем отладку, найдем ошибку и покончим с ней?
Вячеслав, долго я возился с этой ошибкой, но, наконец-то ее разрешил. Решение неочевидное. MtApi.dll использует библиотеку Newtonsoft.Json.dll Причем, старую, 8-ой версии. Другие мои коннекторы, которые компилируются в ту же папку, что и MtApi.dll тоже используют Newtonsoft.Json.dll, но последней, 10-ой версии. При компиляции в папку сборки попадает 10-ая версия. MtApi.dll вызывает 8-ую версию, ей отвечает 10-ая, вот и ошибка.
Что сделал. При компиляции MtApi.dll указал 10-ую версию, заодно повысил Framework с 4 на 4.5. После этого ошибка исчезла. Благодарю за труды!
Hi @vdemydiuk , I am using MtApi.dll and currently I am having the same issue, I have tried already whatever mentioned in the above comments. I am consuming api in asp.net mvc web, and its working fine but when deployed to iis it throws this no connection error.
I am fighting with this error for last 2 days, any help would be greatly appriciated. Thanks.
Сделал простую программу для тестов MtApi. После подключения раз в 5 секунд по таймеру получаю OrdersTotal(). Сначала все принимается корректно. Примерно через минуту работы получаю:
MtApi.MtConnectionException: Client is not connected. ---> System.ServiceModel.CommunicationException: Client is not connected. в MTApiService.MtClient.SendCommand(Int32 commandType, ArrayList parameters, Dictionary
2 namedParams, Int32 expertHandle) в MtApi.MtApiClient.SendCommand[T](MtCommandType commandType, ArrayList commandParameters, Dictionary
2 namedParams)Начал искать причину ошибки.
Проверяется свойство IsConnected
private bool IsConnected => _proxy.State == CommunicationState.Opened;
_proxy класса MtApiProxy. Этот класс наследуется от DuplexClientBase. Тот наследуется от ClientBase. В нем реализовано свойство State: