Task.cancel() isnt stopping my task

I’m trying to create an emote in which accessories will given to the player then removed mid-way through, I’ve decided to try and create a task that would then stop if the player were to switch or stop the emote.

The problem I’m currently having is that using Task.cancel() on my thread does not cancel it and will continue to run even after the animation has stopped, I am also receiving zero errors (this is all taking place in the same local script inside the player’s gui)

Task being created:

--- make task ---------------
		effectfunction = task.spawn(function()
			songinstance.Played:Connect(function()
				if currentemote.Value == script.Parent.Name then
					task.wait(10.683)
					local sax = game:GetService("ReplicatedStorage").emoteeffects.stockdancin.Saxophone
					local glasses = game:GetService("ReplicatedStorage").emoteeffects.stockdancin.sunglasses
					local clonedsax = sax:Clone()
					local clonedglasses = glasses:Clone()
					clonedsax.Parent = character
					clonedglasses.Parent = character
					addAccoutrement(character, clonedglasses)
					addAccoutrement(character, clonedsax)
					script.hatstuff:FireServer(sax, "add")
					script.hatstuff:FireServer(glasses, "add")
					wait(9.75)
					for _, v in pairs(character:GetChildren()) do
						if v:IsA("Accessory") and v.Name == clonedsax.Name then
							v:Destroy()
						end
					end
					for _, v in pairs(character:GetChildren()) do
						if v:IsA("Accessory") and v.Name == clonedglasses.Name then
							v:Destroy()
						end
					end
					script.hatstuff:FireServer(sax, "remove")
					script.hatstuff:FireServer(glasses, "remove")

					songinstance.Ended:Connect(function()
						songinstance:Play()
						dance:Stop(0)
						dance:Play(0)
					end)
				end
			end)
		end)
		-----------------------

How im trying to close it:

currentemote.Changed:Connect(function(val)
	if currentemote.Value ~= script.Parent.Name then
		print(effectfunction == coroutine.running())
		task.cancel(effectfunction)
		print("stopped function")
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == "Saxophone" then
				v:Destroy()
			end
		end
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == "sunglasses" then
				v:Destroy()
			end
		end
	end
end)

how its showing in game:


Any help is appreciated, thank you!

2 Likes

The problem is that the connection callback function is dispatched in a different thread. Cancelling the thread where you connected the event won’t prevent the event from continuing execution, it immediately completes and enters a dead state because the Connect function doesn’t yield.

Instead, you should dispatch a task inside of the event itself in a scope visible to the function that tries to cancel it:

local effectTask: task?

songinstance.Played:Connect(function()
	if currentemote.Value ~= script.Parent.Name then
		return
	end
	
	if effectTask then
		task.cancel(effectTask)
	end
	
	effectTask = task.delay(10.683, function ()
		local sax = game:GetService("ReplicatedStorage").emoteeffects.stockdancin.Saxophone
		local glasses = game:GetService("ReplicatedStorage").emoteeffects.stockdancin.sunglasses
		local clonedsax = sax:Clone()
		local clonedglasses = glasses:Clone()
		clonedsax.Parent = character
		clonedglasses.Parent = character
		addAccoutrement(character, clonedglasses)
		addAccoutrement(character, clonedsax)
		script.hatstuff:FireServer(sax, "add")
		script.hatstuff:FireServer(glasses, "add")
		wait(9.75)
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == clonedsax.Name then
				v:Destroy()
			end
		end
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == clonedglasses.Name then
				v:Destroy()
			end
		end
		script.hatstuff:FireServer(sax, "remove")
		script.hatstuff:FireServer(glasses, "remove")

		songinstance.Ended:Connect(function()
			songinstance:Play()
			dance:Stop(0)
			dance:Play(0)
		end)
	end)
end)
currentemote.Changed:Connect(function(val)
	if currentemote.Value ~= script.Parent.Name then
		if effectTask then
			task.cancel(effectTask)
		end
		print("stopped function")
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == "Saxophone" then
				v:Destroy()
			end
		end
		for _, v in pairs(character:GetChildren()) do
			if v:IsA("Accessory") and v.Name == "sunglasses" then
				v:Destroy()
			end
		end
	end
end)
4 Likes

Cannot thank you enough, I am not used to how tasks work so this is greatly appreciated!

1 Like

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