Подписка и отписка SetUpdateCallback

Страницы: 1
RSS
Подписка и отписка SetUpdateCallback, Подписка и отписка SetUpdateCallback
 
Привет,

Я делаю подписку CreateDataSource и SetUpdateCallback условно по TQBR GAZP по дневному интервалу. Пока что все OK - данные начинают приходить.
Потом я делаю отписку от CreateDataSource и SetUpdateCallback вызывая "Close".  На удивление пока что все тоже хорошо, данные больше не обновляются и не приходят.

ТЕПЕРЬ я опять подписываюсь на TQBR GAZP по дневному интервалу. И вот хрен - никаких данных уже не приходит.

Разработчики - прошу подтвердить или не подтвердить - что это ожидаемое поведение или баг.
 
https://forum.quik.ru/messages/forum10/message68501/topic7641/#message68501
 
Цитата
paluke написал:
https://forum.quik.ru/messages/forum10/message68501/topic7641/#message68501
Благодарствую, сработало.
 
На самом деле проблема стара как этот мир (в нашем случае квик), сейчас продемонстрирую на небольшом примере.
1) Вариант просто создаю таблицу с методами.
2) "Танцы с бубнами" - Моя древняя функция боюсь ее уже даже руками трогать.
Код
function main() 
    message('Стратегия 3ТФ запущена: ' ..  CLASS_CODE ..'; '..SEC_CODE )

    DS = {}
    DS.D1 = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL_D1)
    DS.H1 = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL_H1)
    DS.M1 = CreateDataSource(CLASS_CODE, SEC_CODE, INTERVAL_M1)
    message( 1)..' '.. type(DS.D1) .. ' DS.D1:Size() ' .. tostring(DS.D1:Size()) .. ' DS.H1:Size() ' .. tostring(DS.H1:Size()) .. ' DS.M1:Size() ' .. tostring(DS.M1:Size()) )

    DS.D1 = Source(CLASS_CODE, SEC_CODE, INTERVAL_D1)
    DS.H1 = Source(CLASS_CODE, SEC_CODE, INTERVAL_H1)
    DS.M1 = Source(CLASS_CODE, SEC_CODE, INTERVAL_M1)
    message(2)..' '..  type(DS.D1) .. ' DS.D1:Size() ' .. tostring(DS.D1:Size()) .. ' DS.H1:Size() ' .. tostring(DS.H1:Size()) .. ' DS.M1:Size() ' .. tostring(DS.M1:Size()) )
   while is_run do
А вот ответы
Стратегия 3ТФ запущена: SPBFUT; MXM5
1) table DS.D1:Size() 0 DS.H1:Size() 0 DS.M1:Size() 0
2) table DS.D1:Size() 162 DS.H1:Size() 1485 DS.M1:Size() 11247
 
1.
Цитата
VPM написал:
На самом деле проблема стара как этот мир (в нашем случае квик)
  Скрипты в QUIKе это программы реального времени, в которых существенен фактор времени.
  В коде, выложенном ниже, определена функция CreateDS, которая дожидается появления данных DS.

Код

stopped = false

function main()
   -------------------------------------------------------
   -- Создание параметризированной функции-замыкания коллбека (с дополнительными (кроме index)  
   -- параметрами ds и par, задаваемыми в момент создания). 
   --    Использование  ds:SetUpdateCallback(CreateUpdateCallbackDS(func, ds, par))
   --        параметр par необязателен, но если он fаlse, то тело функции не выполняется.
   --  ! Исключения в функции коллбека перехватываются. Коллбек при этом отключается с выдачей сообщения об исключении.
   --  Параметры: 
   --     func(index, ds, par) - функция  обработки коллбеков (вызываемых по изменениям свечи) --
   --     ds - открытый источник;
   --     par - параметр  (может отсутствовать) --
   --     index - индекс свечи при выполнении коллбека; 
   --  Результат: параметризированная функция-замыкание - параметр для функции ds:SetUpdateCallback ---
   local CreateUpdateCallbackDS = function(func, ds, par)
      return
         function(index)           -- Обертка для func  --
            if par ~= false then
               local kod, mes = pcall(func, index, ds, par) -- в защищенном режиме --
               if mes then
                  message('Исключение в коллбеке (он отключен, его 3-й параметр : '.. tostring(par) .. '). Текст исключения: ' .. mes, 3)
                  par = false
               end
            end
         end
   end
   --------------------------------------------------
   ---  Cl - класс, Sec - код бумаги, Int - таймфрейм.
   ---  T - ожидание поступления данных источника в сек. (по умолчанию 15 сек.)
   local CreateDS = function(Cl, Sec, Int, T)
      T = (T or 15) * 10
      local ds, Error = CreateDataSource(Cl, Sec, Int)
      for i = 1, T do
         if not ((Error == "" or Error == nil) and ds:Size() == 0) then break end 
         if i == T then error('Не дождались DS: ' .. Sec .. '. Ошибка: ' .. tostring(Error)) end
         sleep(100)
      end
      return ds
   end
   ---------------------------------------------------
   -- Вариант многократно используемой параметризированной заготовки для создания коллбеков в CreateUpdateCallbackDS --
   local function cb_p(index, ds, sec_code)
      local t = ds:T(index)
      local _str = string.format("#%d of %d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f %02d.%02d.%04d %02d:%02d:%02d.%04d\n",
      index, ds:Size(),ds:O(index), ds:H(index), ds:L(index), 
      ds:C(index), ds:V(index),
      t.day, t.month, t.year, t.hour, t.min, t.sec, t.ms)
      message(sec_code .. ': ' .. _str)
   end
   ---------
   local ds
   local function cb(index)  -- одноразовая функция коллбека -
      local t = ds:T(index)
      local _str = string.format("#%d of %d\t%.4f\t%.4f\t%.4f\t%.4f\t%.4f %02d.%02d.%04d %02d:%02d:%02d.%04d\n",
      index, ds:Size(),ds:O(index), ds:H(index), ds:L(index), 
      ds:C(index), ds:V(index),
      t.day, t.month, t.year, t.hour, t.min, t.sec, t.ms)
      message(_str)
   end
   ds = CreateDS("QJSIM", "GAZP", INTERVAL_M1)
message('Size = ' .. ds:Size())
   -- Вариант с созданием функции-замыкания, выдающей сообщение об исключениях во время ее выполнения ---
   ds:SetUpdateCallback(CreateUpdateCallbackDS(cb)) 
   
   -- ds:SetUpdateCallback()                                -- 1. #### это не помогает
   -- ds:SetUpdateCallback(function() end)                  -- 2. #### и это не помогает
   ds:Close() -- ?? После Close повторно установленные один раз коллбеки не срабатывают (
              -- хотя источник открывается)

   ds = CreateDS("QJSIM", "GAZP", INTERVAL_M1)
 
   -- ds:SetUpdateCallback(function() end) -- 3. #### это тоже помогает вместо последующего ds:SetUpdateCallback(cb)
   ds:SetUpdateCallback(cb) -- Обычный вариант (если в функции коллбека cb возникает исключение, 
                            -- то коллбек перестает выполняться, но сообщения об этом нет)
   ds:SetUpdateCallback(
                  CreateUpdateCallbackDS(cb_p, ds, "GAZP")) -- 4. #### Повторная установка параметризированного 
                                             --  коллбека. Если это закомментировать, то коллбек не запускается
   -- ds:SetUpdateCallback(cb)      -- 5. #### Это , вместо пункта 4, тоже проходит
    
   
   while not stopped do 
      sleep(3000)
-- message('while Size = ' .. ds:Size())
   end 
end  

function OnStop(row)
    stopped = true
end
---
--  Резюме (смотрите комментарии, выделенные строкой ####).
--- После ds:Close(), ds = CreateDataSource(...) повторно установленный коллбек cb не срабатывает 
--  (хотя источник открывается и свечи приходят).
--  Но если устанавливать два раза: ds:SetUpdateCallback(cb)   ds:SetUpdateCallback(cb),то cb срабатывает --


2.  В том же коде определена функция  CreateUpdateCallbackDS - создание параметризированных замыканий-коллбеков на основе функций заготовок (в коде примера: функция cb_p). Функцию-заготовку можно использовать, создавая коллбеки для многих разных источников DS. При этом обеспечивается выдача сообщений об исключениях времени выполнения колбека (что не делается штатными средствами).

3. В коде комментариями, помеченными строкой ####, описываются "танцы с бубном" с тем, чтобы повторно подключить коллбек к повторно открытому DS.
  Вопрос к поддержке: что еще надо показать, чтобы стало ясно, что в ds:Close() есть ошибка?
 
Поддержка вместо 1. #### и 2.#### предлагала SetEmptyCallback() перед Close().
 
Цитата
paluke написал:
Поддержка вместо 1. #### и 2.#### предлагала SetEmptyCallback() перед Close().
   Да. Это работает. Но в документе: функция SetEmptyCallback позволяет получать данные с сервера.  И нет описания, что Close не закрывает источник без предварительного вызова SetEmptyCallback.
Страницы: 1
Читают тему
Наверх