我正在學習 Rust 并嘗試制作一個簡單的egui GUI 應用程式,該應用程式在單獨的執行緒中輪詢 telnet 主機,以避免主執行緒鎖定 GUI。我正在為客戶端使用telnet crate。
這是我遇到問題的代碼:
struct TelnetApp {
gui_status: AppView,
telnet_ip: String,
telnet_port: String,
telnet_connect_failed_display: bool,
telnet_connect_failed_message: String,
telnet_client: Arc<Mutex<Option<Telnet>>>,
telnet_result : Arc<Mutex<String>>,
}
impl TelnetApp {
// Called from gui after successfully connecting to Telnet host
fn start_telnet_loop(&mut self) {
let arc_telnet_result = self.telnet_result.clone();
let arc_telnet_client = self.telnet_client.clone();
let time = SystemTime::now();
thread::spawn(move || { // <---- ERROR: `(dyn Stream 'static)` cannot be sent between threads safely
loop {
thread::sleep(Duration::from_millis(1000));
arc_telnet_client.lock().unwrap().unwrap().read(); // <--- This line causes error
{
// I can read and modify the String, presumably because it implements Send?
*arc_telnet_result.lock().unwrap() = String::from(format!("Time {}", time.elapsed().unwrap().as_micros()));
}
}
});
}
}
正如我用評論標記的那樣,執行緒生成行給了我一個錯誤,這似乎源于 arc_telnet_client 沒有實作特征“發送”這一事實,因為洗掉該行時錯誤消失了:
arc_telnet_client.lock().unwrap().unwrap().read()
我讀到包裝Arc<Mutex<>>是處理多執行緒的推薦方法,但這仍然沒有給出特征發送。
為什么我的方法不允許,即使我使用互斥鎖來鎖定它?你將如何實作這樣一個簡單的輪詢執行緒?
uj5u.com熱心網友回復:
為什么我的方法不允許,即使我使用互斥鎖來鎖定它?
因為!Send意味著物件根本不安全地移動到不同的執行緒。不管你如何保護它,它只是無效的。
例如,它可能正在使用執行緒本地資料,或內核任務資源,或某種不受保護的全域或共享狀態,或親和機制。無論如何或為什么,如果它是!Send,它只能從創建它的執行緒訪問,無論你將它包裝在什么中。一個例子是MutexGuard:
impl<T: ?Sized> !Send for MutexGuard<'_, T>
這是因為互斥鎖通常只能從鎖定它們的執行緒中解鎖(它是 posix 中的 UB,Windows 上的發布失敗)
正如其特征所描述的,如果一個物件是,則 Mutex 是同步的(因此可以在執行緒之間共享)Send:
impl<T: ?Sized Send> Sync for Mutex<T>
這是因為從語意上講,在 Send 周圍有一個互斥鎖等同于通過通道將包裝物件從一個執行緒移動到下一個執行緒(包裝物件將始終一次從一個執行緒使用)。
另一方面,RwLock 需要,Sync因為可以從不同的執行緒(在讀取模式下)同時訪問包裝的物件:
impl<T: ?Sized Send Sync> Sync for RwLock<T>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qiye/513744.html
標籤:多线程锈
上一篇:記錄--前端校招位元組面試分享
