This is indeed a non-obvious error message. Have a look at the method signatures for unwrap: 
pub fn unwrap(self) -> T
and take:
pub fn take(&mut self) -> Option<T>
unwrap consumes the Option (note the receiver is self), which would leave self.dispatch_thread in an unknown state. If you use take it is returned to the None state as you probably intended.
You probably want take in this context; as shown here:
use std::thread;
use std::time;
struct Foo {
    foo: Option<thread::JoinHandle<()>>,
}
impl Foo {
    fn nope(&mut self) {
        self.foo = Some(thread::spawn(|| {
            for _i in 1..10 {
                println!("Price = {}", 10);
                thread::sleep(time::Duration::from_millis(10));
            }
        }));
        self.foo.take().unwrap().join();
    }
}
fn main() {
    let foo = Some(thread::spawn(|| {
        for _i in 1..10 {
            println!("Price = {}", 10);
            thread::sleep(time::Duration::from_millis(10));
        }
    }));
    foo.unwrap().join();
    let mut foo = Foo { foo: None };
    foo.foo = Some(thread::spawn(|| {
        for _i in 1..10 {
            println!("Price = {}", 10);
            thread::sleep(time::Duration::from_millis(10));
        }
    }));
    foo.foo.unwrap().join();
    let mut foo = Foo { foo: None };
    foo.nope();
}
Note that assert!(foo.foo.is_none()); would be similarly illegal; but is valid in this case because we don't violate that constraint. In the method with &self as a receiver, this isn't true, which is why it is illegal in that case.