Добрый день,
Нет, так сделать нельзя, и вот почему. Здесь возможны два варианта -
либо вы перемещаете self в новый поток, либо вы вызываете метод на
self из нового потока по ссылке. В первом варианте вы не сможете
создавать потоки в цикле - очевидно, self может быть перемещён только
в один из них (и к тому же это нельзя сделать в принципе, если метод
принимает &self, поскольку из-под ссылки перемещать данные нельзя). Во
втором варианте возникает проблема такого рода:
let v = vec![1, 2, 3];
{
let v_ref = &v;
spawn(move || {
timer::sleep(Duration::seconds(3));
println!("{}", v_ref[0]);
});
}
drop(v);
Ссылка передаётся в поток, а объект, на который она указывает,
дропается в другом потоке (выходит из области видимости и
деструктурируется). Получается висящая ссылка. Из-за этого передавать
нестатические ссылки между потоками небезопасно.
Самый простой способ решить вашу проблему - клонировать self перед
отправкой в поток:
for data in ... {
let data = ...;
let self_cloned = self.clone();
spawn(move || {
println!("handle -> {}", self_cloned.handle(data));
});
}
Безусловно, в этом случае MyStruct должна реализовывать Clone.
Если это для вас не подходит, то вам нужно будет использовать Arc<T>.
В идеале вы могли бы объявить, что методы принимают self через Arc<T>,
но я не уверен, что это сейчас сработает:
fn start(self: Arc<MyStruct>) { ... }
fn handle(self: Arc<MyStruct>) { ... }
Так что вам придётся сделать свободные функции вместо методов, которые
будут использовать Arc<MyStruct> (или Arc<Mutex<MyStruct>>, если к
структуре нужен мутабельный доступ):
fn start(my_struct: Arc<MyStruct>) {
for data in ... {
let data = ...;
let my_struct = my_struct.clone();
spawn(move || {
println!("handle -> {}", handle(my_struct, data));
});
}
}
Кажется, что handle() всё же можно сделать методом, который принимает
&self, а не Arc<MyStruct>, но это уже детали; start() в любом случае
должен принимать Arc<MyStruct>.
24 декабря 2014 г., 0:51 пользователь gig kaz <
cht...@gmail.com> написал:
> --
> Вы получили это сообщение, поскольку подписаны на группу "Rust по-русски".
> Чтобы отменить подписку на эту группу и больше не получать от нее сообщения,
> отправьте письмо на электронный адрес
>
rust-russian...@googlegroups.com.
> Чтобы посмотреть обсуждение на веб-странице, перейдите по ссылке
>
https://groups.google.com/d/msgid/rust-russian/1372c4fc-5dcb-4095-a5a8-c746103aa6d3%40googlegroups.com.
> Чтобы настроить другие параметры, перейдите по ссылке
>
https://groups.google.com/d/optout.