Mahlukat Posted January 9, 2019 Share Posted January 9, 2019 Hey i have a export function for dbQuery but when i call func, data from database stay late I searched the forum and found a few solutions with coroutine but I could not :(( anyone can explain how's work coroutine and what should i do please function querydb(str) if str:find("DROP TABLE") then return end local id = getFreeID() local co = nil function verileriAktar(sorgu) coroutine.resume(co, sorgu) end co = coroutine.create(function() dbQuery(verileriAktar,connection,str) local results = coroutine.yield() local cevap = dbPoll(results,0) queries[id] = cevap print(id) end) coroutine.resume(co) -- should stop here i guess but its not print("cevap: "..id) return id end local id = querydb("SOME DB CODES") -- cevap: 1 -- 1 Link to comment
Moderators IIYAMA Posted January 9, 2019 Moderators Share Posted January 9, 2019 This is not how you use coroutines. Databases and coroutines are two very different things. But for what kind of reason do you want to use a coroutines? dbQuery is already providing you with a callback option. https://wiki.multitheftauto.com/wiki/DbQuery Optional Arguments callbackFunction: An optional function to be called when a result is ready. The function will only be called if the result has not already been read with dbPoll. The function is called with the query handle as the first argument. (Notice: Do not use a function with a local prefix) If you want to improve your database performance, then write better queries with limiters. Link to comment
Mahlukat Posted January 9, 2019 Author Share Posted January 9, 2019 34 minutes ago, IIYAMA said: But for what kind of reason do you want to use a coroutines? Thanks you for your answer When i call querydb function, its return before dbQuery's callback function and i thought maybe querydb function can wait for dbQuery's callback function because i have a another function like this; function getQueryResult(id) if not queries[id] then return false end return queries[id] end I am using exactly like this; local id = querydb("SOME DB FUNCS") local result = getQueryResult(id) Link to comment
Moderators IIYAMA Posted January 9, 2019 Moderators Share Posted January 9, 2019 You can do that, but the coroutine has to be placed around this: -- couroutine function local id = querydb("SOME DB FUNCS") local result = getQueryResult(id) -- function something () local co = coroutine.create(function () local id = querydb(co, "query") local result = querydb(co, "query") end) coroutine.resume(co) -- start the coroutine end function querydb (co, query) -- ... local callBackFunction = function () coroutine.resume(co) -- resume! end -- execute the query here! coroutine.yield() -- freeze! return results end Something like that. 1 Link to comment
Moderators IIYAMA Posted January 9, 2019 Moderators Share Posted January 9, 2019 local co co = coroutine.create(function () * Link to comment
Mahlukat Posted January 9, 2019 Author Share Posted January 9, 2019 i dont understand im so confused would you create some example too please Link to comment
Moderators IIYAMA Posted January 9, 2019 Moderators Share Posted January 9, 2019 A coroutine is a function block which can be frozen with: coroutine.yield() This function has to be called during the execution of the block. It doesn't have to be in the same block, but within the code that is executed in the block. The resume function can be called from where ever you want. It can be used to start the executing the coroutine function. But also to resume a frozen(yield) coroutine function. coroutine.resume(co) When a coroutine function has been executed till the end, the status of the coroutine function is considered dead. It can't be resumed any more. 1 Link to comment
Addlibs Posted January 9, 2019 Share Posted January 9, 2019 (edited) I believe coroutines cannot be sent over via callback arguments, so you'll have to store the coroutine reference in a table t at some index i and then send i for callback, and resume t[ i ] in the callback function. gDatabaseConnection = --[[ this would be your database connection here ]] local coroutines = {} -- coroutines will be stored here function gCallbackFn(qh, id) -- this is called when dbQuery thread returns indicating the query is ready to poll local result = dbPoll(qh, 0) -- since it's ready to poll, timeout is irrelevant and can be 0 coroutine.resume(coroutines[id], result) -- resume the coroutine with query result data end function handleQuery(queryStr, ...) if not coroutine.running() then error("handleQuery can only be called from within a coroutine.", 2) end local id = table.maxn(coroutines) + 1 -- calculate next unused table index (not sure whether # or maxn is better here) coroutines[id] = coroutine.running() -- store this coroutine in that table index dbQuery(gCallbackFn, {id}, gDatabaseConnection, queryStr, ...) -- this splits into two threads, first one continutes over to coroutine.yield function, other is internal to MTA and handles the query, and continues from gCallbackFn afterwards. local qData = coroutine.yield() -- since we want to wait for the query thread to return, we need to yield/pause this coroutine execution, and let gCallbackFn resume it when the query thread returns return qData -- return the query result data end -- now call handleQuery at some arbitrary point, here, after 1000ms (1s) c = coroutine.wrap( -- coroutine.wrap creates a coroutine wrapped in a function that, when called, will start/resume the coroutine function() local result = handleQuery("SELECT * sometable WHERE id = ?", 2) iprint(result) end ) setTimer(c, 1000, 1) -- call the function-wrapped coroutine after 1000ms I've only tested this using timers instead of dbQuery but it should work. N.B. this handleQuery function must be called from within a coroutine. If you're calling this when an event happens, you can override addEventHandler to automatically wrap handlers into coroutines too. local addEventHandler_ = addEventHandler function addEventHandler(eventName, attachedTo, handlerFn, propagation, priority) return addEventHandler_(eventName, attachedTo, coroutine.wrap(handlerFn), propagation, priority) end Edited January 9, 2019 by MrTasty 1 Link to comment
Recommended Posts
Create an account or sign in to comment
You need to be a member in order to leave a comment
Create an account
Sign up for a new account in our community. It's easy!
Register a new accountSign in
Already have an account? Sign in here.
Sign In Now