← Назад

Вопрос по архитектуре библиотеки

Добрый день.

Предположим, что необходимо получать данные по инструментам, для этого мы добавляем нужные столбцы в квике и в программе, подписываемся на событие новой записи и изменения данных в таблице Secirities и в обработчике Trader.Connected запускаем экспорт по DDE этой таблицы. Данные поступают, мы их видим как в обработчиках событий, так и в таблице Trader.Securities. Далее есть два варианта:

  1. в любой момент времени мы можем обратиться к данной таблице из кода стратегии и прочитать нужные нам данные;
  2. в обработчиках событий копировать поступившие данные в свои структуры и в стратегии работать со своими данными.

Интересует такой вот момент, во втором случае разработчик сам занимается вопросом согласованности данных, т.е. любая запись и доступ к данным заключены в блок синхронизации и в любой момент времени данные у нас согласованы. Каким образом обстоит дело в первом случае?

Комментарии (15)

Вход или Создать аккаунт, Войдите или зарегистрируйтесь, чтобы оставить комментарий

Mikhail Sukhov
Mikhail Sukhov

esper: т.е. любая запись и доступ к данным заключены в блок синхронизации и в любой момент времени данные у нас согласованы.

Это не так. Объекты торговых типов обновляются без какой-либо синхронизации, и не атомарно.

esper
esper Автор

Mikhail Sukhov: Это не так. Объекты торговых типов обновляются без какой-либо синхронизации, и не атомарно.

Т.о. получается, что когда я в событии изменения записи таблицы (SecurityChanged) копирую данные из пришедшего объекта в свою внутреннюю структуру они могут поменяться? Может имеет смысл добавить хотя SyncRoot для возможности lock-а или сделать по принципу много читателей - один писатель?

Mikhail Sukhov
Mikhail Sukhov

esper:

Mikhail Sukhov: Это не так. Объекты торговых типов обновляются без какой-либо синхронизации, и не атомарно.

Т.о. получается, что когда я в событии изменения записи таблицы (SecurityChanged) копирую данные из пришедшего объекта в свою внутреннюю структуру они могут поменяться? Может имеет смысл добавить хотя SyncRoot для возможности lock-а или сделать по принципу много читателей - один писатель?

А зачем?

Maxim
Maxim

Мне кажется вы друг друга недопонимаете.

На мой взгляд, esper хотел спросить: являются ли свойства объекта класса QuikTrader потокобезопасными? И насколько я знаю, ответ: да, являются.

Михаил, поправьте меня, если я ошибаюсь.

Попутный уточняющий вопрос: а все ли свойства потокобезопасны? В частности интересует свойство Security.ExtensionInfo Необходима ли синхронизация этого свойства при доступе из разных потоков?

Mikhail Sukhov
Mikhail Sukhov

Maxim: В частности интересует свойство Security.ExtensionInfo Необходима ли синхронизация этого свойства при доступе из разных потоков?

Смотря что Вы с ним хотите делать. Если просто сделать так var info = sec.ExtensionInfo;, а если ``` sec.ExtensionInfo.Contains(key);

esper
esper Автор

Mikhail Sukhov: А зачем?

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

Mikhail Sukhov: Смотря что Вы с ним хотите делать. Если просто сделать так var info = sec.ExtensionInfo;, а если ``` sec.ExtensionInfo.Contains(key);


Почему в первом случае нет необходимости в синхронизации? ExtensionInfo вроде ссылочный тип, при таком присваивании данные не копируются, просто получаем еще один указатель на словарь🤨
Maxim
Maxim

Mikhail Sukhov: Смотря что Вы с ним хотите делать. Если просто сделать так var info = sec.ExtensionInfo;, а если ``` sec.ExtensionInfo.Contains(key);



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


Я хочу в одном потоке записывать в это свойство данные, а в другом потоке читать эти данные.
Необходимо ли синхронизовать эти потоки, что бы они одновременно не имели доступ к этому свойству?
Или эта синхронизация реализована внутри свойства?
Mikhail Sukhov
Mikhail Sukhov

Maxim: Я хочу в одном потоке записывать в это свойство данные, а в другом потоке читать эти данные. Необходимо ли синхронизовать эти потоки, что бы они одновременно не имели доступ к этому свойству? Или эта синхронизация реализована внутри свойства?

Да, нужно. Это вариант 2.

esper
esper Автор

Mikhail Sukhov:

Maxim: Я хочу в одном потоке записывать в это свойство данные, а в другом потоке читать эти данные. Необходимо ли синхронизовать эти потоки, что бы они одновременно не имели доступ к этому свойству? Или эта синхронизация реализована внутри свойства?

Да, нужно. Это вариант 2.

А каким образом можно сделать синхронизацию с внутренним обновлением этих данных? Чтобы пока я их читаю они не менялись?

Mikhail Sukhov
Mikhail Sukhov

esper: А каким образом можно сделать синхронизацию с внутренним обновлением этих данных? Чтобы пока я их читаю они не менялись?

Наверное никак, так как никакой синхронизации в обновлении данных нет. А в чем заключается сама задача?

esper
esper Автор

Mikhail Sukhov:

esper: А каким образом можно сделать синхронизацию с внутренним обновлением этих данных? Чтобы пока я их читаю они не менялись?

Наверное никак, так как никакой синхронизации в обновлении данных нет. А в чем заключается сама задача?

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

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

Mikhail Sukhov
Mikhail Sukhov

esper: Я считываю одно поле для конкретного инструмента в начале функции, далее выполняю другие действия, из квика приходят новые данные, считываю другое поле для этого же инструмента и получаю несогласованные данные.

Можете эти поля указать?

Maxim
Maxim

Михаил, добрый день. Еще один вопрос про потоки.

Каким образом можно перебрать все элементы свойства QuikTrader.MyTrades?

Если применить к этому свойству foreach, то в процессе работы цикла к этому свойству из другого потока могут добавится новые элементы и foreach может сработать некорректно(может пропустить некоторые элементы).

Соответственно, что бы применить foreach к QuikTrader.MyTrades, нужно на время выполнения этого цикла блокировать изменение этого свойства. Есть ли такая возможность? Например, публичный объект для блокировки?

Или есть другой способ выполнить задачу?

Mikhail Sukhov
Mikhail Sukhov

Maxim: Михаил, добрый день. Еще один вопрос про потоки.

Каким образом можно перебрать все элементы свойства QuikTrader.MyTrades?

Напрямую. Всегда возвращается копия данных, которая не модифицируется.

Maxim: Если применить к этому свойству foreach, то в процессе работы цикла к этому свойству из другого потока могут добавится новые элементы и foreach может сработать некорректно(может пропустить некоторые элементы).

Попробуйте так сделать. Ошибка будет совсем другая.

Maxim: Соответственно, что бы применить foreach к QuikTrader.MyTrades, нужно на время выполнения этого цикла блокировать изменение этого свойства. Есть ли такая возможность? Например, публичный объект для блокировки?

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

Maxim
Maxim

Mikhail Sukhov: Напрямую. Всегда возвращается копия данных, которая не модифицируется.

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

Итак, насколько я понял если во время выполнения следующего кода из Квика придет новая моя сделка, то она в цикл никак не попадет?


foreach (MyTrade myTrade in Global.Quik.MyTrades)                        
  if (_newOrder == myTrade.Order)                            
    _volume += myTrade.Trade.Volume;  

Возможно, что бы сто раз одно и то же не объяснять, стоит добавить в документацию раздел с описанием того, что в библиотеке потокобезопасно, а что нет. Хотя понимаю, что на все надо время.