Coroutine.Close doesn't kill all created coroutines

  1. What do you want to achieve? Keep it simple and clear!
    Hi! I am trying to kill every coroutine created by my script

-- a simple Decrease timer function 
local function ChangeTime(v)
	if ( Module.Info[tonumber(v.Name)]["WaitTime"] - Player.Values.DailyPlayedTime.Value ) > 0 then
		v.Text = format_time(math.abs(( Module.Info[tonumber(v.Name)]["WaitTime"] - Player.Values.DailyPlayedTime.Value)))
		while unFormat_time(v.Text) > 1 do
			v.Text = format_time(unFormat_time(v.Text) - 1)
			task.wait(1)
		end
		if unFormat_time(v.Text) == 1 then

			v.Text = "Redeem"
		end
	else
		v.Text = "Redeem"
	end
end

local function Delkit()
	for i,v in pairs(frame:GetDescendants()) do
	  if v:IsA("TextLabel") then
		co = coroutine.create(ChangeTime,v) --Creates coroutine 
		print("HELLO")
		coroutine.resume(co,v) -- Starts coroutine
		end
	end
end
Delkit()

--This is a RemoteEvent fired Every 10 second
Remotes:WaitForChild("ResetRewardCooldown").OnClientEvent:Connect(function()
	for i,v in pairs(frame:GetDescendants()) do
		if v:IsA("TextLabel") then
                       Print("Test)
			coroutine.close(co) -- kill the coroutines  just kills 1 of them?
		end
	end
	
end)
  1. What is the issue? Include screenshots / videos if possible!

as you can see it only stops the last Timer not all of them, Why and how can I stop every coroutine created?

  1. What solutions have you tried so far? Did you look for solutions on the Developer Hub?
    I have read the documentation about coroutines and a few post

After that, you should include more details if you have any. Try to make your topic as descriptive as possible, so that it’s easier for people to help you!

Away from that
I changed coroutine.close(co) to coroutine.yield(co,v) for test purposes but it didn’t do anything at all, can someone explain why? Thanks!

The co variable is being overwritten with every new thread created. In order to access previous threads, they’ll need to be stored in a table that can be accessed elsewhere. I’ve modified your Delkit() and remote handler to do this:

--Store threads in a lookup table where the keys are the TextLabels and the values are the threads.
local timerThreads = {}

local function Delkit()
	for i,v in pairs(frame:GetDescendants()) do
		if v:IsA("TextLabel") then
			timerThreads[v] = task.spawn(ChangeTime, v)	--Creates and runs thread, adding it to the table.
		end
	end
end
Delkit()

--This is a RemoteEvent fired Every 10 second
Remotes:WaitForChild("ResetRewardCooldown").OnClientEvent:Connect(function()
	for i,v in pairs(frame:GetDescendants()) do
		if v:IsA("TextLabel") then
			local thread = timerThreads[v]	--Finds the thread associated with this TextLabel (if it exists).
			
			--If the thread exists and is currently suspended, then it can be closed.
			if thread then
				timerThreads[v] = nil	--Remove from table to prevent memory leaks.
				if coroutine.status(thread) == "suspended" then
					task.cancel(thread)
				end
			end
		end
	end
end)

If you want to kill all timers no matter what, though, you don’t need to fetch the threads based on their associated TextLabels and could just iterate through the table, closing each thread.

2 Likes

Thanks

it worked

so after creating the last thread I am losing access of previous threats and coroutine.close part was actually worked
But I have a question why coroutine.yield didn’t stopped last timer? while coroutine.close stops it?

coroutine.yield() can only yield the thread that calls it, which ends up being the main thread and not the co thread. The arguments you provide to it get passed up to whatever code resumed the coroutine rather than the function doing anything to the arguments specifically. coroutine.close() on the other hand does accept a thread argument and closes what is passed to it.

1 Like

Thanks for the explaination!
I really appreciate it

1 Like

sorry if I am bothering you with this question but I have wondered something while re-reading the code

at this part Thread runs so it is in “Running” state

so
Why at this part Thread’s status is equals to “Suspended”
is it because we removed threads from the table?

local thread = timerThreads[v]	--Finds the thread associated with this TextLabel (if it exists).
			
			--If the thread exists and is currently suspended, then it can be closed.
			if thread then
				timerThreads[v] = nil	--Remove from table to prevent memory leaks.
				if coroutine.status(thread) == "suspended" then
					task.cancel(thread)
				end
			end

and another thing is (Well this is not a question but)
we can check the status of a thread that is created by task.spawn?
I thought coroutine was an alternative version of Task library

The coroutine library is the original Lua implementation of threads. ROBLOX added the task library to enhance it and to get it to play better with the engine. One big enhancement is that errors in threads created by the task library properly show up in the output, which is huge for debugging.

task.spawn() generates a thread, then immediately resumes it with the arguments you pass to it. It isn’t that functionally different than doing the same via coroutine.create() and coroutine.resume() other than that it is one line. The similar coroutine method coroutine.wrap() can’t be used in this case because that function won’t give you a reference to the new thread.

Regardless of which library you’re using, threads enter a “suspended” state whenever they yield, and they can only be canceled when they are in the “suspended” or “dead” states, although “dead” threads have either already completed their task or have crashed, so there isn’t a point to canceling them.

I check the status of thread before acting on them just to be prudent, but in a lot of cases it isn’t really necessary since the status of a thread accessed from outside the scope it was created in will really only ever be “suspended” or “dead.”

Threads can be in a “running” state, but you will only ever see this if you check the status of the current thread via coroutine.status(coroutine.running()). They can also be in a “normal” state if the status of a higher-scope thread is checked by a thread it created, such as via this:

local thread = coroutine.running()
task.spawn(function()
	print(coroutine.status(thread))
end)

When threads are in the “running” or “normal” states, attempting to close them will throw an error.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.