I also ran up against the Lua execution time limit in an addon I was developing this month. I solved this using coroutines.
The issue is that there is a hard limit on the execution time allowed for scripts per frame rendered to the screen - to prevent the game freezing up while a long script executes.
The fix is relatively simple. Turn your slow function into a coroutine, then call coroutine.yield() to pause it during the slow part of the script (e.g. inside a loop or wherever).
Then you want to make a handler, say stepCoroutine(), that steps through your slow function (now coroutine), let's call it myCoroutine(). You build the step-through handler something like this:
local myCoroutine = nil
local function stepCoroutine()
-- if coroutine is finished
if not myCoroutine or coroutine.status(myCoroutine) == "dead" then
myCoroutine = nil
return
end
-- step the coroutine
local success, error = coroutine.resume(myCoroutine)
if not success then
-- some error here, handle it however you like (e.g. combat lockdown)
end
-- if coroutine isn't finished step it on next game frame
if coroutine.status(myCoroutine) ~= "dead" then
C_Timer.After(0, stepCoroutine)
else
-- we finished!
end
end
To actually start the coroutine wherever it needs to be in your code you would do something like:
myCoroutine = coroutine.create(function()
-- some code here
for _, item in ipairs(mySlowLoop) do
-- do some stuff then pause
coroutine.yield()
end
-- do more stuff
end)
-- then just call the step-through function to actually start it:
stepCoroutine()
This is just a basic skeleton / example, of course you can fully tailor it to your needs. In my addon I also tracked combat lockdown and had a frame register for when it ended to resume my coroutine etc, but that is not at all required if you aren't doing anything that could cause tainted execution.
Anyway, that is how I would suggest getting around the execution time per frame limit.
I also ran up against the Lua execution time limit in an addon I was developing this month. I solved this using coroutines.
The issue is that there is a hard limit on the execution time allowed for scripts per frame rendered to the screen - to prevent the game freezing up while a long script executes.
The fix is relatively simple. Turn your slow function into a coroutine, then call
coroutine.yield()to pause it during the slow part of the script (e.g. inside a loop or wherever).Then you want to make a handler, say
stepCoroutine(), that steps through your slow function (now coroutine), let's call itmyCoroutine(). You build the step-through handler something like this:To actually start the coroutine wherever it needs to be in your code you would do something like:
This is just a basic skeleton / example, of course you can fully tailor it to your needs. In my addon I also tracked combat lockdown and had a frame register for when it ended to resume my coroutine etc, but that is not at all required if you aren't doing anything that could cause tainted execution.
Anyway, that is how I would suggest getting around the execution time per frame limit.