Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

SendCommand: Client is not connected Error #74

Open
cia76 opened this issue Dec 18, 2017 · 16 comments
Open

SendCommand: Client is not connected Error #74

cia76 opened this issue Dec 18, 2017 · 16 comments
Labels

Comments

@cia76
Copy link

cia76 commented Dec 18, 2017

Сделал простую программу для тестов MtApi. После подключения раз в 5 секунд по таймеру получаю OrdersTotal(). Сначала все принимается корректно. Примерно через минуту работы получаю:

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, Dictionary2 namedParams)

Начал искать причину ошибки.

        /// <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

private bool IsConnected => _proxy.State == CommunicationState.Opened;

_proxy класса MtApiProxy. Этот класс наследуется от DuplexClientBase. Тот наследуется от ClientBase. В нем реализовано свойство State:

    public CommunicationState State
    {
        get
        {
            IChannel channel = (IChannel)this.channel;
            if (channel != null)
            {
                return channel.State;
            }
            else
            {
                // we may have failed to create the channel under open, in which case we our factory wouldn't be open
                if (!this.useCachedFactory)
                {
                    return GetChannelFactory().State;
                }
                else
                {
                    return CommunicationState.Created;
                }
            }
        }
    }
@vdemydiuk
Copy link
Owner

Добрый день.
Можно ли вас попросить сбросить мне вашу программу на почту [email protected]? Я проверю ее у себя.

@cia76
Copy link
Author

cia76 commented Dec 20, 2017

Похоже, ошибка происходит только тогда, когда идет обращение из разных потоков. Я запускаю один поток вначале для получения исторических данных. Затем запускаю таймер раз в 5 секунд для проверки заявок и позиций. Раз в минуту запускается поток обновления исторических данных. Когда каждый поток первый раз обращается к статичному свойству MtApiClient, то получаю ошибку.

Попробую сделать тестовый код, который воспроизводит ошибку. Весь проект слишком сложный, да и не нужен он весь.

@vdemydiuk
Copy link
Owner

Вообще-то нет смысла проверять состояние коннекта по таймеру. Для этого есть ивент ConnectionStateChanged который отлично подходить для этого и выдает нотификации, если состояние поменяется. Попробуйте использовать его.

@cia76
Copy link
Author

cia76 commented Dec 20, 2017

Это понятно. Интересует не состояние соединения, а новые заявки, которые появились за последние 5 секунд. Как я понимаю, в MT4 события постановки заявки/позиции нет.

@vdemydiuk
Copy link
Owner

Все верно, таких событий нет.
Но есть уже готовая реализация TradeMonitor (TimerTradeMonitor, TimeframeTradeMonitor), который выдает ивенты по закрытым и открытим ордерам. Возможно это то, что вам нужно.

@cia76
Copy link
Author

cia76 commented Dec 21, 2017

Продолжаю отладку. Перед тем как получаю ошибку, то вижу, что ((System.ServiceModel.ClientBase<MTApiService.IMtApi>)(MTApiClient.Client._proxy)).State переходит из статуса Open в статус Close.

channel при этом существует. Вопрос становится таким: При каких обстоятельствах происходит разрыв соединения? Чтобы статус сменился с Open на Close нужно принудительно закрыть канал методом Close();

Пройдя по исходникам, я не нашел ситуаций принудительного разрыва соединения.

@vdemydiuk
Copy link
Owner

Это очень странная ситуация, когда канал произвольно закрывается. Мне нужно исходники примера с данной проблемой, чтобы воспроизвести ее локально и попробовать определить ее характер.

@cia76
Copy link
Author

cia76 commented Dec 21, 2017

Возвращаясь к исходному коду:

        /// <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? В каком случае может быть ситуация, когда прокси не подключен?

Насчет кода. Если я упрощаю код и вывожу код из своего проекта, то он работает ОК. Поэтому, я постепенно усложняю тестовый вариант до тех пор, пока не поймаю ошибку.

@vdemydiuk
Copy link
Owner

Проверка выполняется лишь с той целью, что пользователь может случайно сделать вызов функции API без подключения. При всегда правильном вызове функций это проверка немного избыточна.

@cia76
Copy link
Author

cia76 commented Jan 16, 2018

Добрый день! Извиняюсь за запоздалый ответ. Если работать с MTApi из нескольких потоков одновременно, то канал, действительно, закрывается через произвольное время. Пришлось решать задачу через управление потоками. Чтобы в текущий момент времени только 1 поток мог работать с MTApi. После этого, описанная мною ошибка, исчезла. Если появится снова, то отпишусь в этой ветке. Благодарю за MTApi!

@cia76
Copy link
Author

cia76 commented Jan 19, 2018

Все-таки, ошибка есть. Работаю в одном 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, Dictionary2 namedParams)

Ошибка происходит на разных компьютерах под Windows 10 со всеми установленными обновлениями.

@vdemydiuk
Copy link
Owner

Буду пробовать воспроизвести эту проблему со своей стороны. Надеюсь получиться в скором времени ее пофиксить.

@cia76
Copy link
Author

cia76 commented Jan 22, 2018

Погонял код прошлую неделю. Если через интервалы от 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, Dictionary2 namedParams)
--- Конец трассировки внутреннего стека исключений ---
в MtApi.MtApiClient.SendCommand[T](MtCommandType commandType, ArrayList commandParameters, Dictionary`2 namedParams)

@cia76
Copy link
Author

cia76 commented Feb 16, 2018

Вячеслав, мне отписался наш трейдер. У него возникает та же самая ошибка. Может, сделаем отладку, найдем ошибку и покончим с ней?

@cia76
Copy link
Author

cia76 commented Sep 27, 2018

Вячеслав, долго я возился с этой ошибкой, но, наконец-то ее разрешил. Решение неочевидное. MtApi.dll использует библиотеку Newtonsoft.Json.dll Причем, старую, 8-ой версии. Другие мои коннекторы, которые компилируются в ту же папку, что и MtApi.dll тоже используют Newtonsoft.Json.dll, но последней, 10-ой версии. При компиляции в папку сборки попадает 10-ая версия. MtApi.dll вызывает 8-ую версию, ей отвечает 10-ая, вот и ошибка.

Что сделал. При компиляции MtApi.dll указал 10-ую версию, заодно повысил Framework с 4 на 4.5. После этого ошибка исчезла. Благодарю за труды!

@abdullahkhan-devops
Copy link

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.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

3 participants