To give some context, I have the following snippet in part of my code:
async {
self.stream.as_mut().unwrap().send(Message::Close(None)).await;
let close = self.stream.as_mut().unwrap().next().await;
thread::sleep(Duration::from_millis(1000));
assert!(self.stream.as_mut().unwrap().next().await.is_none());
self.stream.as_mut().unwrap().close(None).await;
}
(Actually, the async block is longer, but for exemplifying I believe this suffices).
Here, self.stream is an Option<WebsocketStream<...>> which I am trying to close with this code. After sending the close message and receiving the ack, I’d test effectively having close the connection via receiving nothing when asking for a new message. Yet if I don’t sleep between the ack and the call to next, I’d still receive something and theis_none assertion fails.
I’d interpret that awaiting for the ack means that the assertion would only be tested once the await has returned. But this failing when the sleeping is not present makes me doubt it is the case. Am I missing something?
I am relatively new to asyncronous code, so the question may be basic, and this is what I understood from the async book. The questions I found on SO seem to refer mostly to C# async statements, which I don’t know are equivalent to Rust’s ones.
Thank you very much in advance.
>Solution :
await does not block the current thread. It yields to another coroutine on the same thread. thread::sleep does block the current thread, which is why you should never use it in async code. Instead, you’d use something like tokio::time::sleep, which is async and yields. As the book says:
Whereas calling a blocking function in a synchronous method would block the whole thread, blocked Futures will yield control of the thread, allowing other Futures to run.
That said, if you need to wait 1 second for your test to pass, you may need to rethink the order of operations in your close. That may be indicating a race condition. I’m not familiar with which crate you’re using here to know if this is expected for a unit test.