You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -29,7 +28,7 @@ but it is not unusual wanting to run a slightly longer operation in one go.
29
28
30
29
## How to Avoid Blocking the Main Loop
31
30
32
-
In order to avoid blocking the main loop we can spawn a new thread with [`gio::spawn_blocking`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/gio/fn.spawn_blocking.html) and let the operation run there.
31
+
In order to avoid blocking the main loop we can spawn a new task with [`gio::spawn_blocking`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/gio/fn.spawn_blocking.html) and let the operation run there.
> If you come from another language than Rust, you might be uncomfortable with the thought of spawning new threads before even looking at other options.
47
+
> If you come from another language than Rust, you might be uncomfortable with the thought of running tasks in separate threads before even looking at other options.
49
48
> Luckily, Rust's safety guarantees allow you to stop worrying about the nasty bugs that concurrency tends to bring.
50
49
51
50
51
+
Typically, we want to keep track of the work in the task.
52
+
In our case, we don't want the user to spawn additional tasks while an existing one is still running.
53
+
In order to achieve that we can create a channel with the crate [`async-channel`](https://docs.rs/async-channel/latest/async_channel/index.html).
54
+
Let's add it by executing the following in the terminal:
55
+
56
+
```
57
+
cargo add async-channel
58
+
```
52
59
53
-
Normally we want to keep track of the work in the thread.
54
-
In our case, we don't want the user to spawn additional threads while an existing one is still running.
55
-
In order to achieve that we can create a channel.
56
-
The main loop allows us to send a message from multiple places to a single receiver at the main thread.
57
60
We want to send a `bool` to inform, whether we want the button to react to clicks or not.
61
+
Since we send in a separate thread, we can use [`send_blocking`](https://docs.rs/async-channel/latest/async_channel/struct.Sender.html#method.send_blocking).
62
+
But what about receiving?
63
+
Every time we get a message we want to set the sensitivity of the button according to the `bool` we've received.
64
+
However, we don't want to block the main loop while waiting for a message to receive.
65
+
That is the whole point of the exercise after all!
66
+
67
+
We solve that problem by waiting for messages to receive in an [`async`](https://rust-lang.github.io/async-book/) block.
68
+
We spawn that `async` block on the glib main loop with [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local) (from other threads than the main thread [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) has to be used).
<p>The button now stops being responsive for 10 seconds after being pressed</p>
69
84
</video>
70
85
</div>
71
86
72
-
73
-
> Per default, [`glib::clone!`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/macro.clone.html) returns `()` when upgrading of a weak reference fails.
74
-
> [`glib::Receiver::attach`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.Receiver.html#method.attach) expects a closure with a return value of type [`glib::ControlFlow`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/enum.ControlFlow.html).
75
-
> This is why we specify `@default-return` as `glib::ControlFlow::Break` to clarify that the closure not be called anymore as soon as the upgrade of a weak reference fails.
76
-
77
-
78
-
Spawning threads is not the only way to run operations asynchronously.
79
-
You can also let the main loop take care of running [`async`](https://rust-lang.github.io/async-book/) functions.
80
-
If you do that from the main thread use [`spawn_local`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn_local), from other threads [`spawn`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/struct.MainContext.html#method.spawn) has to be used.
81
-
The converted code looks and behaves very similar to the multi-threaded code.
87
+
What if the task is asynchronous by nature?
88
+
Let's use [`glib::timeout_future_seconds`](https://gtk-rs.org/gtk-rs-core/stable/latest/docs/glib/fn.timeout_future_seconds.html) as representation for our task instead of `std::thread::slepp`.
89
+
It returns a [`std::future::Future`](https://doc.rust-lang.org/std/future/trait.Future.html), which means we can `await` on it within an `async` context.
90
+
The converted code looks and behaves very similar to the multithreaded code.
0 commit comments