Concurrency
Threads
Rust’s standard library provides OS threads via std::thread:
use std::thread;
use std::time::Duration;
let handle = thread::spawn(|| {
thread::sleep(Duration::from_millis(100));
println!("from thread");
});
handle.join().unwrap();
println!("from main");In C#: Like new Thread(() => { ... }).Start() and thread.Join(). Or Task.Run for thread-pool threads.
move closures
If a closure captures a variable by reference, the closure might outlive the variable. To transfer ownership into the thread, use move:
let v = vec![1, 2, 3];
let handle = thread::spawn(move || {
println!("{:?}", v); // v is moved into the closure
});
handle.join().unwrap();In C#: Similar to capturing variables in a lambda passed to Task.Run; in C# the closure captures by reference unless you copy. In Rust, move makes the closure take ownership.
Channels (mpsc)
Rust provides multiple-producer, single-consumer channels for passing messages between threads:
use std::sync::mpsc;
use std::thread;
let (tx, rx) = mpsc::channel();
thread::spawn(move || {
tx.send(42).unwrap();
});
let received = rx.recv().unwrap();
println!("got {}", received);In C#: Like Channel<T> or a producer-consumer queue. Shared state is avoided; communication is by message passing.
In C#: Concurrency is often done with async/await and Task; in Rust you can use threads + channels for CPU-bound or blocking work, or async for I/O-bound work (see Async module).
Key takeaway
Use thread::spawn for threads; use move when the closure must own captured data. Use mpsc::channel() for message passing between threads. Prefer channels over shared mutable state.