Как чистить память?
Atom
16.08.2013
Bond


Просто включаю и выключаю коннектор к Квику. И с каждым перезапуском он все тяжелее загружает данные, а потом на 4-5 включении выбрасывает с ошибкой о переполнении памяти. С каждым включением он съедает 400 Мб оперативной памяти, а после отключения её не выгружает. Только когда закрываешь окно коннектора он освобождает память. Код отключения у меня как из уроков:
Код

public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if(Trader!=null && Trader.IsConnected)
            {
                Trader.StopExport();
                Trader.Disconnect();
                
            }
        }

Dispose() не помогает!!!

Теги:


Спасибо:


IvanB

Фотография
Дата: 16.08.2013
Ответить


Bond
Просто включаю и выключаю коннектор к Квику. И с каждым перезапуском он все тяжелее загружает данные, а потом на 4-5 включении выбрасывает с ошибкой о переполнении памяти. С каждым включением он съедает 400 Мб оперативной памяти, а после отключения её не выгружает. Только когда закрываешь окно коннектора он освобождает память. Код отключения у меня как из уроков:
Код

public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if(Trader!=null && Trader.IsConnected)
            {
                Trader.StopExport();
                Trader.Disconnect();
                
            }
        }

Dispose() не помогает!!!

Убедитесь, что DisConnectSafe вызывается при отключении коннектора, и если в обычном виде (код выше) мусор из памяти не освобождается, то сделайте так:
Код

public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if(Trader!=null)
            {
                if (Trader.IsConnected)
                {
                   Trader.StopExport();
                   Trader.Disconnect();
                }
                Trader.Dispose();
                Trader=null;
                GC.Collect();
            }
        }
Спасибо:

Bond

Фотография
Дата: 20.08.2013
Ответить


IvanB
Bond
Просто включаю и выключаю коннектор к Квику. И с каждым перезапуском он все тяжелее загружает данные, а потом на 4-5 включении выбрасывает с ошибкой о переполнении памяти. С каждым включением он съедает 400 Мб оперативной памяти, а после отключения её не выгружает. Только когда закрываешь окно коннектора он освобождает память. Код отключения у меня как из уроков:
Код

public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if(Trader!=null && Trader.IsConnected)
            {
                Trader.StopExport();
                Trader.Disconnect();
                
            }
        }

Dispose() не помогает!!!

Убедитесь, что DisConnectSafe вызывается при отключении коннектора, и если в обычном виде (код выше) мусор из памяти не освобождается, то сделайте так:
Код

public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if(Trader!=null)
            {
                if (Trader.IsConnected)
                {
                   Trader.StopExport();
                   Trader.Disconnect();
                }
                Trader.Dispose();
                Trader=null;
                GC.Collect();
            }
        }


Эффекта 0! При пошаговой проверке оказалось, что после Trader.Disconnect(), Trader.Dispose(), GC.Collect() память уменьшается на 10-20Мбайт не более, а вся прога жрет под 300Мбайт.
А при Trader=null; при повторном запуске при нажатии на кнопку вылетает по Эксепшену. И правильно на мой взгляд делает. Вообще эту строку закомментил.
Может не освобождает потому, что Trader где-то ещё используется? Я к сожалению в тонкостях не разбираюсь...
Код

using System;
using System.IO;
using System.Linq;
using Ecng.Collections;
using StockSharp.Algo;
using StockSharp.BusinessEntities;
using StockSharp.Quik;

namespace StockSharp.TraderConnection
{
    /// <summary>
    /// Безопасное подключение
    /// </summary>
    public class SafeConnection
    {
        /// <summary>
        /// Коннектор к торговой платформе
        /// </summary>
        public BaseTrader Trader { get; private set; }

        /// <summary>
        /// Событие появления нового исключения
        /// </summary>
        public event Action<Exception> NewException = delegate { };

        /// <summary>
        /// Конструктор. Создать безопасное подключение
        /// </summary>
        /// <param name="trader">Коннектор к торговой платформе</param>
        public SafeConnection(BaseTrader trader)
        {
            Trader = trader;
        }

        /// <summary>
        /// Вызвать событие появления нового исключения
        /// </summary>
        /// <param name="exception">Исключение</param>
        protected virtual void OnNewException(Exception exception)
        {
            //Вызвать событие появления нового исключения
            NewException(exception);
        }

        /// <summary>
        /// Подключиться безопасно к торговой платформе
        /// </summary>
        public void _ConnectSafe()
        {
            //Интервал переподключения
            Trader.ReConnectionSettings.Interval = TimeSpan.FromSeconds(10);
            //Когда переподключаться
            Trader.ReConnectionSettings.WorkingTime = ExchangeBoard.Forts.WorkingTime;
            //Запускать ли заново экспрорт после переподключения
            Trader.ReConnectionSettings.IsReStartExport = true;
            //Подписаться на появление ошибки подключения от трейдера
            Trader.ConnectionError += OnNewException;
            //Подписаться на появление ошибок не выставленной заявки
            Trader.OrdersRegisterFailed += fails => fails.ForEach(f => OnNewException(f.Error));
            //Подписаться на событие успешного подключения к торговой платформе
            Trader.Connected += () =>
                                    {
                                        try
                                        {
                                            //Запустить экспорт данных из торговой платформы
                                            Trader.StartExport();
                                        }
                                        catch (Exception ex)
                                        {
                                            //Вызвать событие появления нового исключения
                                             OnNewException(ex);
                                        }
                                    };

            //Подключиться к торговой платформе
            Trader.Connect();
        }

        public void ConnectSafe()
        {
            const string pathKey = (@"C:\Key_Junior\Key_Junior.txt");

            var pathFile = File.ReadLines(pathKey).Skip(0).First();

            var terminal = QuikTerminal.Get(pathFile);

            if (!terminal.IsLaunched)
            {
                Console.WriteLine("Запускается Quik...");

                terminal.Launch();

                Console.WriteLine("Quik запущен");
            }


            if (!terminal.IsConnected)
            {
                var login = File.ReadLines(pathKey).Skip(1).First();

                var password = File.ReadLines(pathKey).Skip(2).First();

                terminal.Login(login, password);

                Console.WriteLine("Авторизация произведена");

            }
            if (terminal.IsConnected) _ConnectSafe();


        }

        /// <summary>
        /// Разорвать соединение с торговой платформой
        /// </summary>
        public void DisConnectSafe()
        {
            //Если коннектор к торговой платформе не пуст и соединение установлено
            if (Trader != null)
            {
                if (Trader.IsConnected)
                {
                    Trader.StopExport();
                    Trader.Disconnect();
                }
                Trader.Dispose();
                // Trader = null;
                GC.Collect();
            }
        }

        /// <summary>
        /// Возвращает. установлено ли соединение с торговй платформой
        /// </summary>
        public bool IsConnected
        {
            get
            {
                return Trader != null && Trader.IsConnected;
            }
        }
    }
}


Код

using System;
using System.Collections.Generic;
using System.Windows;
using System.Windows.Controls;
using Ecng.Xaml;
using StockSharp.Algo.Strategies;
using StockSharp.BusinessEntities;
using StockSharp.TraderConnection;

namespace StockSharp.WpfConnectionInterface
{
    /// <summary>
    /// Логика взаимодействия для UserControl1.xaml
    /// </summary>
    public partial class InterFace : UserControl
    {
        //Поле, безопасный коннектор
        private SafeConnection _safeConnection;

        /// <summary>
        /// Безопасный коннектор
        /// </summary>
        public SafeConnection SafeConnection 
        { 
            set
            {
                _safeConnection = value;
                //Изменить доступность кнопки в соответствии с состоянием переменной _safeConnection
                btnConnect.IsEnabled = _safeConnection!=null;
            }
            get { return _safeConnection; }
        }

        /// <summary>
        /// Конструктор
        /// </summary>
        public InterFace()
        {
            InitializeComponent();

            //Событие завершения загрузки данного контрола
            Loaded += InterFace_Loaded;

            //Сделать кнопку не доступной
            btnConnect.IsEnabled = false;
        }

        /// <summary>
        /// Событие завершения загрузки данного контрола
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="routedEventArgs"></param>
        void InterFace_Loaded(object sender, RoutedEventArgs routedEventArgs)
        {
            //Получить родительское окно
            var window = Window.GetWindow(Parent);
            if (window != null)
                window.Closed += delegate
                    {
                        if (_safeConnection != null)
                            _safeConnection.DisConnectSafe();
                    };
        }

        /// <summary>
        /// Выбранный инструмент
        /// </summary>
        public Security SelectedSecurity
        {
            get { return (Security)cbSecurities.SelectedItem; }
        }

        /// <summary>
        /// Выбранный портфель
        /// </summary>
        public Portfolio SelectedPortfolio
        {
            get { return (Portfolio)cbPortfolios.SelectedItem; }
        }

        /// <summary>
        /// Нажатие на кнопку подключения
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void ConnectClick(object sender, RoutedEventArgs e)
        {
            if (_safeConnection == null)
                return;

            if (_safeConnection.IsConnected)
            {
                btnConnect.Content = "Отключаем";
                btnConnect.Background = System.Windows.Media.Brushes.OrangeRed;
                cbPortfolios.Background = System.Windows.Media.Brushes.LightPink;
                cbSecurities.Background = System.Windows.Media.Brushes.LightPink;
                btnConnect.IsEnabled = false;
                
                //Отписаться от события появления новых инструментов
                _safeConnection.Trader.NewSecurities -= Trader_NewSecurities;
                //Отписаться от события появления новых портфелей
                _safeConnection.Trader.NewPortfolios -= Trader_NewPortfolios;

                //Объявляем действие, которое нужно выполнить при отключении от торговой платформы
                Action disconnected = null;
                disconnected = () =>
                    {
                        _safeConnection.Trader.Disconnected -= disconnected;
                        this.GuiAsync(() =>
                            {
                                btnConnect.IsEnabled = true; btnConnect.Content = "Отключен";
                            });
                    };
                _safeConnection.Trader.Disconnected += disconnected;
                
                //Разорвать соединение
                _safeConnection.DisConnectSafe();
            }
            else
            {
                btnConnect.Content = "Подключаем";
                btnConnect.Background = System.Windows.Media.Brushes.LimeGreen;
                if ( SelectedPortfolio != null) cbPortfolios.Background = System.Windows.Media.Brushes.LightGreen;
                if ( SelectedSecurity != null) cbSecurities.Background = System.Windows.Media.Brushes.LightGreen;
                btnConnect.IsEnabled = false;

                //Подписаться на событие появления новых инструментов
                _safeConnection.Trader.NewSecurities += Trader_NewSecurities;
                //Подписаться на событие появления новых портфелей
                _safeConnection.Trader.NewPortfolios += Trader_NewPortfolios;

                //Объявляем действие, которое нужно выполнить при подключении к торговой платформе
                Action connected = null;
                connected = () =>
                {
                    _safeConnection.Trader.Connected -= connected;
                    this.GuiAsync(() => { btnConnect.IsEnabled = true; btnConnect.Content = "Включен"; });
                };
                _safeConnection.Trader.Connected += connected;

                //Подключиться безопасно
                _safeConnection.ConnectSafe();

            }
        }

        /// <summary>
        /// Появление новых портфелей
        /// </summary>
        /// <param name="portfolios"></param>
        private void Trader_NewPortfolios(IEnumerable<Portfolio> portfolios)
        {
            this.GuiAsync(() =>
                {
                    cbPortfolios.ItemsSource = _safeConnection.Trader.Portfolios;
                    cbPortfolios.Background = System.Windows.Media.Brushes.LightGreen;
                });
        }
        
        /// <summary>
        /// Появление новых торговых инструментов
        /// </summary>
        /// <param name="securities"></param>
        private void Trader_NewSecurities(IEnumerable<Security> securities)
        {
            this.GuiAsync(() =>
                {
                    cbSecurities.ItemsSource = _safeConnection.Trader.Securities;
                    cbSecurities.Background = System.Windows.Media.Brushes.LightGreen;
            });
        }

        public void PushInformationToStrategy(Strategy strategу)
        {
            strategу.Trader = SafeConnection.Trader;
            strategу.Portfolio = SelectedPortfolio;
            strategу.Security = SelectedSecurity;
        }

        private void cbSecurities_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {

        }
    }
}

Спасибо:

Bond

Фотография
Дата: 21.08.2013
Ответить


Почему память может не высвобождаться? Или такая ерунда только у меня?
Спасибо:

IvanB

Фотография
Дата: 21.08.2013
Ответить


Bond
Почему память может не высвобождаться? Или такая ерунда только у меня?


Пришлите проект на почту iv_qul@list.ru будем разбираться.
Спасибо:

IvanB

Фотография
Дата: 22.08.2013
Ответить


Просмотрел я проект, выяснил, что проблема увеличения занятой памяти связана с увеличивающимся кол-вом вызовов метода Trader.StartExport(); при каждом нажати на кнопку для подключения к терминалу.
Это связано с тем, что перед каждым подключением к терминалу выполняется следующее:
Код

                                    Trader.Connected += () =>
                                    {
                                        try
                                        {
                                            //Запустить экспорт данных из торговой платформы
                                            Trader.StartExport();
                                        }
                                        catch (Exception ex)
                                        {
                                            //Вызвать событие появления нового исключения
                                             OnNewException(ex);
                                        }
                                    };

но при этом нигде не вызывается Trader.Connected -= ...
Т.о. событие Trader.Connected имеет все большее и большее кол-во экземпляров одного и того же обработчика, из-за чего и вызывается несколько раз метод Trader.StartExport(); при появлении одного события Trader.Connected.
Выход: инициализировать объект Trader в отдельном методе (где есть код Trader.Connected += ...), только один раз, а не при каждом нажатии на кнопку подключения, либо при отключении от терминала выполнять код: Trader.Connected -= ...
Спасибо:


Добавить файлы через драг-н-дроп, , или вставить из буфера обмена.

loading
clippy