← Zurück

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

Добрый день.

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

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

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

War dieses Thema hilfreich?

Thema teilen

Kommentare (15)

Anmelden oder Konto erstellen, Melden Sie sich an oder registrieren Sie sich, um einen Kommentar zu hinterlassen

Mikhail Sukhov
Mikhail Sukhov

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

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

esper
esper Autor

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 Autor

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 Autor

Mikhail Sukhov:

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

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

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

Mikhail Sukhov
Mikhail Sukhov

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

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

esper
esper Autor

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;  

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