День добрый. Хочу, чтобы текущая функция, приостановилась, пока не разрешу идти дальше. Не флагом рубить всю функцию, и колбэком каким-нибудь его скидывать, а прямо посреди работы функции. Это возможно сделать? Есть такой функционал? Что то типа заморозки, а когда можно - отморозить. Но, конечно , не завесить весь терминал и другие скрипты. И сразу еще вопрос. Выход из функции возможен только через return 0 ? Есть что-то вроде break и continue?
Michael Bulychev, добрый день! По разным источникам стараюсь разобраться с корутинами, раз уж без них никак. Пожалуйста, подскажите, что не так делаю?
Задача следующая. Выставляю ордер на продажу. Хочу, чтобы после отправки заявки, функция приостановилась и возобновила работу после получения и обработки ответа от OnOrder.
Часть кода без входных переменных и инициализации, убрал лишнее
Код
function _SellOpt(trid,price,qty,mode,comment)
-----------
local command =---------
PrintDbgStr(COMMENT_ALL..": Отправляю команду в терминал на Продажу _SellOpt(trid,price,qty,mode,comment)")
local _commToQuik = sendTransaction(command)
return 0
end
function OnOrder(trans_order)
PrintDbgStr("В онордере прошло событие ")
if trans_order["sec_code"] == SECCODE and trans_order["brokerref"] == COMMENT_ALL and trans_order["class_code"] == CLASSCODE then table.sinsert(ORDER_TABLE,1,trans_order)
is_run = false
coroutine.resume(co)
end
end
function bots()
PrintDbgStr("В BOTS скрипте даем команду на продажу")
_SellOpt(TRID_TRADE,2000,QTY,MODE,COMMENT_ALL)
PrintDbgStr("BOTS залип")
coroutine.yield()
PrintDbgStr("BOTS отлип")
end
function main( ... )
while is_run do
PrintDbgStr("В основном скрипте пошел прогон")
co = coroutine.create(bots())
sleep(2000)
end
end
После исполнения скрипт, выставив заявку останавливается с ошибкой в окне доступных скриптов:
Код
attempt to yield across metamethod/C-call boundary
Лог:
Код
00000001 12:23:37 [7844] SR6500BF5//SCRYPT: Инициализация прошла
00000002 12:23:37 [7844] В основном скрипте пошел прогон
00000003 12:23:37 [7844] В BOTS скрипте даем команду на продажу
00000004 12:23:37 [7844] SR6500BF5//SCRYPT: Проверка цены на существенный выход. Цена в установленных пределах _VerifyPriceToTheor(price,direction)
00000005 12:23:37 [7844] SR6500BF5//SCRYPT: Отправляю команду в терминал на Продажу _SellOpt(trid,price,qty,mode,comment)
00000006 12:23:37 [7844] BOTS залип
Мою логику, исполнения, думаю, понять не трудно. Но очевидно, что делаю не верно.
Добрый день. Логику пока не понял, похоже Вам не нужны корутины. Пример кода с Вашей ошибкой:
Код
function test()
print(1)
coroutine.yield()
end
co = coroutine.create(test()) -- вот тут ошибка, надо так: co = coroutine.create(test)
--[[
1
C:\Program Files (x86)\Lua\5.1\lua.EXE: attempt to yield across metamethod/C-call boundary
stack traceback:
[C]: in function 'yield'
c.lua:3: in function 'test'
c.lua:10: in main chunk
[C]: ?
--]]
Да, ошибка перестала выскакивать, спасибо. Но все это время пытаюсь заставить скрипт работать как мне надо - не получается. Многое уже поменял. Михаил, скажите, пожалуйста, реально ли воплотить на корутинах такую логику:
майн запускает корутину. в ней функция выставления ордера на продажу. после выставления прерываю её через coroutine.yield() Хочу чтобы функция дальше не работала, а ждала resume от OnOrder Пришло подтверждение - работаем дальше.
Как я это делаю - работает не понятно как. Статус корутины то normal, то running, то вдруг dead, хотя до конца функция в корутине не доработала.. Может я и все правильно делаю, может эти корутины в квике как-то работают особенно, что моей логике не поддаются? Их вообще используют? А то может бьюсь головой о стену..
По-моему речь про то, что человеку нужна синхронная отправка транзакции с ожиданием на неё ответа, и лишь после получения ответа на транзакцию продолжение работы. Может её стоит добавить в QLua? выглядит разумно для написания не событийных роботов а-ля QLIPE-стайл
Мне приходится её ожидать, чтобы не было двойных/тройных заявок. Скрипт входит по несколько раз пока не пришла информация. Конечно, можно рубить флагами, флаги сбрасывать по событиям. Потом еще наслаиваются фокусы с двойными подтверждениями.. потому и пришел к этой задаче. Реализовать - не получается пока. Умирает корутина и все.. Почему -не знаю, даже тему отдельную создал
Наверное, я это и делаю. Я хочу, чтобы скрипт не работал дальше пока не придет подтверждение. Это и есть синхронная работа. Но просто завешивать его циклом (а вместе с ним, наверное, и другие скрипты) я не хочу. Вот и пытаюсь тоже самое сделать через корутины и их приостановки/возобновление. Но вот ведут они себя не понятно. Я не программист, потому мне и непонятно) То была активна то вдруг умерла.. Еще пару дней или завтра побьюсь о них и брошу. Я бы не стал особо за них цепляться, если бы Михаил не посоветовал. К его мнению прислушиваюсь. Но, конечно, может он и не понял задачу и посоветовал то, что работать не будет, тем более что потом отписался, что может и не потребуются они. Но они же, блин, как раз вроде то и делают!Ну вот, как то так)
Да, эту ссылку Вы уже мне давали, или еще где от Вас я её видел и просматривал. В моем вопросе, к сожалению, не сдвигает меня с мертвой точки. Но тут, я понимаю, дело во многом во мне. Наверняка. Все-равно спасибо.
Viktor MMM пишет: не работал дальше пока не придет подтверждение. Это и есть синхронная работа. Но просто завешивать его циклом (а вместе с ним, наверное, и другие скрипты) я не хочу.
Виктор.
Цикл ожидания вида
Код
answer_present = false
while not answer_present do
sleep(100)
answer_present = проверяйте ваше условие
end
будучи запущенным в функции main или любой другой вызванной в конечном итоге из main, остановит только эту функцию.
Всем остальным скриптам от этого не холодно и не жарко.
Использование корутин в вашем случае даст только более элегантный код в том случае, если вы с этим механизмом подружитесь. в конце концов, Такой же цикл ожидания все равно будет присутствовать в коде, только уровнем выше (до диспетчера корутин)
Поэтому если вам нужно именно синхронное исполнение транзакции - смело используйте цикл с ожиданием внутри него.
В колбеках так писать нельзя - это подвесит терминал.
s_mike@rambler.ru, да, спасибо, про загрузку колбэков помню. Сейчас еще помучаю корутины с циклом, нашел еще пример и, скорее всего, сделаю как Вы говорите.
PS на простых примерах у меня корутины эти работают, но как появляются колбэки так все сыпется. Что-то я не учитываю.
Вот примерно Ваш алгоритм: ------------------------- 1) в корутине должен быть бесконечный цикл,в котором вы посылаете и останавливаете корутину. 2) когда ответ пришел вы активируете корутину и она снова посылает и останавливается. 3) кроме этого должна быть очередь к корутине 4) корутина пускает из этой очереди если очередь пустая то останавливается 5) кроме того должна быть запись в очередь 6) при записи в очередь,если корутина стоит то запускается.