3 ms·
> It is probably important here to realize that async solves concurrency, not parallelism. You can use async with a single threaded runtime for I/O concurrency
by bkolobara 3y ago
> It is probably important here to realize that async solves concurrency, not parallelism. You can use async with a single threaded runtime for I/O concurrency and mix that with threads for computational parallelism for long running jobs.
In my experience, it's impossible to mix threads and async tasks. They can't communicate or share state. Threads need locks, while async tasks require an awake mechanism. If you just stick to unbounded channels that don't block on send, you can get far, but in 99% cases you will need to decide upfront on a specific approach.
- thinkharderdev 3y agoThis has not been my experience at all. Delegating compute-intensive tasks to rayon inside a tokio runtime is not particularly hard (assuming you can pipeline things to separate IO and compute effectively). A pattern that has worked quite well for me is to use ``` struct ComputeTask { some_state: SomeState, completion: Sender<Output>, } impl ComputeTask { fn run(self) { .. do you compute-intensive stuff self.sender.send(output); } } async fn do_stuff() -> Result<Output> { let (tx,rx) = tokio::sync::oneshot::channel(); let task = ComputeTask { .., tx } rayon::spawn(move || task.run()); rx.await } ```