Can someone explain what's the difference between async methods and creating a thread in Vala? And where I should use one or another in my code?
Threads are independently schedulable while async
methods run in the main thread, that is, they are coroutines. For example, if you block reading a socket in a separate thread, the application can continue running, but if you do this in an async
method, the application will block.
Threads and coroutines (async
methods) can solve some of the same problems, but are generally doing different things. In Gtk+ (and many other GUI systems) only one thread can manipulate the GUI objects and events from GUI objects will only happen in this thread (usually called the event dispatch thread). If another thread wants to access GUI items, it either needs to a) go through some locking procedure or b) send a message to the EDT. This generalises to all inter-thread communication: to communicate between threads or use shared resources, there needs to be locking and communication.
Coroutines are executed in the EDT as “just another event”. Consider a situation where you have a window with a download button. When the user clicks the button, the EDT will start the click handler associated with the button. If that code were to actually attempt to download the file, the GUI would freeze until the file finished downloading. If a coroutine were started, the button's handler would start an async
method that would open a socket and then be told that it isn't ready yet. It would then put the socket and a callback into the EDT's loop (GLib.MainLoop
). The button's handler would finish and the EDT would sit and wait for an event from the X display or socket, then call the right callback to handle it. That allows GUI events to be processed in an interleaved way with socket events. However, only one handler can be working at a time, so handlers need to be able to finish quickly or the application will be unresponsive.
Using coroutines becomes a giant mess of callbacks, but async
methods hide the callbacks so that it looks like straight-line code even though it isn't.
If your task is mostly waiting, then coroutines are the right choice. If your task is busy working, then it will undoubtedly need to go in a thread. Courotines can't exceed more than one CPU's work, while threads can be run in parallel on multiple CPUs. GLib's coroutines also can't easily be mixed with threads: it's not sane to try to have async
methods operate independently in two threads: only the EDT gets to use async
methods.
© 2022 - 2024 — McMap. All rights reserved.