【发布时间】:2018-07-04 07:22:16
【问题描述】:
我正在使用inputbot 编写一个为我的计算机提供一些全局宏的程序。例如,当我按下 h 键时,它应该执行宏输入
你好世界
进入当前应用程序。我试图这样实现它:
extern crate inputbot;
fn main() {
let mut callback = || {
inputbot::KeySequence("Hello World").send();
};
inputbot::KeybdKey::HKey.bind(callback);
inputbot::handle_input_events();
}
然而,当我按下 h 键时,我实际得到的是:
hHHHHHHHHHHHHHHHHHHHHHHHHHEHEHhEhEEHHhEhEhEHhEHHEHHEEHhEHlhEHEHHEHLEHLHeeleleelelelllelelleelehlhehlleeheehelheelleeleelhllllllellelolelellelleoleloloelellololol olollollelllolllol lloo醇○◎升LO lolooloooloo厕所LOWOLO 0 1 OLW WOWO大号WLLOLOW L O,○○○○WOWW低öoOow WWW WOW wowooWWWO oOWRWOoorW¯¯行oOWorororWRRWLR rLROwoRWLWOworo WorrrRWl流öWRLR OLWöOWLDol rollWWLDWowDLlroWWořoWDWOL dorRrwrolrdrrorlrLWDRdodRLowdllrllolrdlrddolrdlrldowldorowlrdlrorloLDLWDLoddlrddlrdldldldrrdordldrlrddrodlrrldoldlrlddldlrdlldlrdlddrlddldddlddlddd P>
宏在每次发送 h 键事件时都会自行触发。 ????
如何防止Fn 在另一个实例仍在运行时再次被调用?这是小型应用程序的主要功能,因此无需担心兼容性问题与。
我天真的尝试修复
这是在main 中添加一个mut running 变量,callback 在运行时将设置为true,或者immediately 在它已经为真时返回:
extern crate inputbot;
use std::time::Duration;
use std::thread::sleep;
fn main() {
let mut running = false;
let mut callback = || {
if running { return };
running = true;
inputbot::KeySequence("Hello World").send();
// wait to make sure keyboard events are done.
sleep(Duration::from_millis(125));
running = false;
};
inputbot::KeybdKey::HKey.bind(callback);
inputbot::handle_input_events();
}
但是,这不会编译:
error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
经过一番阅读,我现在的理解是 Fn 闭包(inputbot 的 .bind() 方法需要)不能拥有任何可变数据,例如捕获的 mut 变量。
也许可以将变量包装在某种非mut 值中?可能是某种锁,以确保潜在的并发安全,比如这个伪代码?
fn main() {
let mut running = false;
let lockedRunning = example::Lock(&running);
let mut callback = || {
{
let mut running = lockedRunning.acquire();
if running { return };
running = true;
}
inputbot::KeySequence("Hello World").send();
// wait to make sure keyboard events are done.
sleep(Duration::from_millis(125));
{
let mut running = lockedRunning.acquire();
running = false;
}
};
}
【问题讨论】:
-
您确定可以保证立即调用回调吗?如果没有,锁可能不是你想要的,因为第一个回调触发的回调可能会在第一个回调返回后调用,所以它可以抓住锁并触发另一轮击键
-
@SvenMarnach 好点,我认为
inputbot没有这样的保证。
标签: concurrency macros rust keyboard-shortcuts