Thread is always active (even when calling wait_to_finish)

:information_source: Attention Topic was automatically imported from the old Question2Answer platform.
:bust_in_silhouette: Asked By szabotudor

Exactly like the title says. I create a thread, it runs one time and the wait_to_finish function does not work. this is my entire code:

extends Spatial

var objects = 0
var block = load("res://Scenes/Blocks/Block.tscn")
var chunks = []
var generator_thread = Thread.new()

onready var gridmap = $GridMap
onready var player = $Player

export var generator_seed = int()
export var generator_height_amplifier = int()
export var chunk_size = int()


func _ready():
	generator_thread.start(self, "generate_chunk", [generator_seed, chunk_size, Vector2(0, 0)])
	generator_thread.wait_to_finish()

func _process(delta):
	$Label.text = String(Engine.get_frames_per_second()) + "\n" + String(objects)
	print(generator_thread.is_active())
	var pos = player.global_transform.origin
	pos = gridmap.world_to_map(pos)
	pos = pos / chunk_size
	pos = Vector2(floor(pos.x), floor(pos.z))
	for x in range(pos.x - 3, pos.y + 3):
		for y in range(pos.y - 3, pos.y + 3):
			if not(generator_thread.is_active()):
				generator_thread = Thread.new()
				generator_thread.start(self, "generate_chunk", [generator_seed, chunk_size, Vector2(x, y)])


func generate_chunk(data):
	var gen_seed = data[0]
	var size = data[1]
	var place = data[2]
	if place in chunks:
		return
	chunks.append(place)
	place = place * size
	var noise = OpenSimplexNoise.new()
	noise.seed = gen_seed
	var cells = []
	
	for x in range(place.x - size, place.x + size):
		for z in range(place.y - size, place.y + size):
			for y in range(0, noise.get_noise_2d(x, z) * generator_height_amplifier + generator_height_amplifier):
				cells.append(Vector3(x, y, z))
	yield(get_tree(), "idle_frame")
	
	for cell in cells:
		gridmap.set_cell_item(cell.x, cell.y, cell.z, 0)
	yield(get_tree(), "idle_frame")
	
	call_deferred("generate_done")


```
func generate_done():
    generator_thread.wait_to_finish()
```



I don't know almost anything about threads, this is the first time I used them in godot, so please explain in noob terms.
:bust_in_silhouette: Reply From: Wakatta

In the native noob language huh, i’m a bit rusty but will try.

The way i see it you’re calling the wait_to_finish() function inside of the generator_thread essentially giving it more work to do.

Also having the wait_to_finish() function called in the _ready() function just after starting it is a bad idea because you’re basically not giving it a chance to do its thing.

Solution
Try using a timer to do your dirty work.

var thread_timer = Timer.new()

in the _ready() function connect the timer to your thread cleanup function

call("connect", "timeout", self, "generate_done")

at the end of your thread start the timer

thread_timer.start()

It’s a good idea to also return something at the end of none interactive threads for e.g return OK to verify things went accordingly.

if wait_to_finish() == OK:
    print("thread successful")

Thanks, it worked!

szabotudor | 2021-02-15 06:23

Please know that what i’ve said above is a super simplification of what’s actually happening and that you should delve deeper into how threads are managed.

You were trying to join and end the thread upon itself and the reason the timer works is because its functionality executes on the main thread.

Wakatta | 2021-02-15 06:44