如何为notify-rust建立外部超时

vs91vp4v  于 2023-02-16  发布在  其他
关注(0)|答案(1)|浏览(153)

我尝试在Ubuntu 20.0.4上使用notify-rust库,但是发出的通知有不可预测的超时。另外,如果我发送几个通知,它们之间有短暂的延迟,结果可能会有所不同(有时我看到所有通知,有时只看到其中的几个)。
我应用的变通方法:

  • 严重Urgency,因此通知将永远显示。
  • 在显示下一个通知之前等待某个操作,这样就不会丢失任何通知。
use notify_rust::{Notification, Urgency};
use std::{thread, time};

fn main() {
    let summaries = ["one", "two"];

    for summary in summaries {
        let handle = Notification::new()
            .summary(summary)
            .urgency(Urgency::Critical)
            .show()
            .unwrap();

        // helps displaying all the notifications
        handle.wait_for_action(|_action| ());

        // delay might vary
        thread::sleep(time::Duration::from_millis(10));
    }
}

我还试验了lib的timeout,但没有得到任何好的结果。
wait_for_action方法的主要问题是,有时在发送通知后屏幕上看不到通知,因此主线程正在等待对该通知的操作,但该操作永远不会发生(没有任何内容可点击)。
我想尝试watchdog方法:启动一个线程,向其中发送通知处理程序,并在超时后关闭通知:

let handle = Notification::new()
            ...

        let thread_handle = handle.clone();

         thread::spawn(move || {
             thread::sleep(time::Duration::from_secs(60));
            thread_handle.close();
        });

        handle.wait_for_action(|_action| ());

我不知道该怎么做。我不能同时为线程和wait_for_action使用handle,因为线程取得了所有权。克隆不能正常工作,它产生的不是NotificationHandle,而是Notification
有没有办法不深入研究notify-rust库的内部结构来解决这个问题?
我想我可以使用完全不同的方法来解决这个问题,这种方法不涉及调用阻塞wait_for_action,但我想知道是否有更优雅的解决方案?

vngu2lb8

vngu2lb81#

我想出了另一个通知和超时的算法:我创建了两个线程,而不是依赖wait_for_action来捕获通知关闭事件:

  • 一个具有相同的wait_for_action,在完成时通过通道发送消息
  • 等待一段时间然后通过同一通道发送同一消息的另一个线程

主线程等待消息并在第一条消息到达时继续。

use notify_rust::{Notification, Urgency};
use std::sync::mpsc;
use std::{thread, time};

fn main() {
    let summaries = ["one", "two"];

    for summary in summaries {
        // establish the channel and a second transmitter for `timeout` thread
        let (handler_tx, rx) = mpsc::channel();
        let timer_tx = handler_tx.clone();

        // no changes here
        let handler = Notification::new()
            .summary(summary)
            .urgency(Urgency::Critical)
            .show()
            .unwrap();

        // `wait_for_action` is wrapped into a thread
        thread::spawn(move || handler.wait_for_action(|_action| handler_tx.send(()).unwrap_or(())));

        // another thread that waits and then sends the same message
        thread::spawn(move || {
            thread::sleep(time::Duration::from_secs(7));
            timer_tx.send(()).unwrap_or(());
        });

        // the main thread that waits for a message from any of senders
        rx.recv().unwrap();

        thread::sleep(time::Duration::from_millis(10));
    }
}

故意忽略消息发送结果:这些消息中只有一个可以成功发送,然后通道超出范围,另一个发送方收到错误,这没关系。
该解决方案有一个缺点:有可能在超时后,不等待前一个通知关闭,就发送另一个通知,我看到第一个通知关闭后,即使主线程结束,那些通知仍然可以显示,所以它们在通知总线上等待。
我还注意到,为NotificationHandler实现的另一种方法可能更适合此任务:on_close,但是它是使用wait_for_action实现的,所以它也是阻塞的,而且我无法使用此方法实现超时后的通知关闭。

相关问题