8个版本 (4个破坏性更新)
| 0.5.0 | 2023年12月26日 |
|---|---|
| 0.4.0-dev.2 | 2023年11月29日 |
| 0.3.0 | 2023年7月28日 |
| 0.2.0 | 2023年7月1日 |
| 0.1.0 | 2022年11月15日 |
#336 in 异步
4,373每月下载量
在 2 crate 中使用
135KB
3.5K SLoC
irondash_run_loop
此crate提供对系统运行循环的一致、跨平台接口。
获取当前线程的RunLoop
let run_loop = RunLoop::current();
如果没有与当前线程关联的RunLoop,则会创建一个。 RunLoop由特定于平台的实现支持
CFRunLoop在iOS和macOS上ALooper在Android上GMainContext在Linux上HWND消息循环在Windows上
从其他线程调用RunLoop
RunLoop既不是 Send,也不是 Sync。与它的所有交互都必须在RunLoop所属的线程上执行。
要从其他线程与RunLoop交互,请使用 RunLoopSender
let run_loop = RunLoop::current();
let sender = run_loop.new_sender();
// sender is Sync, Send and Clone
thread::spawn(move||{
println("Hello from other thread!");
sender.send(||{
println!("Back on RunLoop thread");
});
});
在任何时候,无需RunLoop实例,您都可以请求发送器将闭包发送到主线程。为了使所有平台上的Dart应用程序都起作用,您的Dart应用程序必须依赖于irondash_engine_context插件。
thread::spawn(move||{
let sender = RunLoop::sender_for_main_thread().unwrap();
sender.send(||{
println!("Back on main thread");
// run_loop is main thread run loop
let run_loop = RunLoop::current();
});
});
依赖于irondash_engine_context插件是必要的,因为Rust代码可能是FFI插件的一部分,该插件从UI线程或其他后台隔离区加载,并且在某些平台上,如果没有在主线程上先做一些准备工作,就不可能跳回主线程(这由irondash_engine_context插件的本地代码部分提供便利)。
如果您想在不使用irondash_engine_context插件的情况下使用RunLoop,则可以在主线程上调用RunLoop::set_main_thread()作为RunLoop的第一个方法。
安排定时器
RunLoop也可以用来安排闭包的延迟执行
let run_loop = RunLoop::current();
let handle = run_loop.schedule(Duration::from_secs(10), || {
println!("This will be printed after 10 seconds");
});
RunLoop::schedule 返回一个 Handle 实例。如果句柄在计时器执行之前被丢弃,计时器将被取消。如果您不希望这样,请在句柄上调用 detach。
let run_loop = RunLoop::current();
self.run_loop(Duration::from_secs(10), || {
println!("This will be printed after 10 seconds");
}).detach();
您还可以调用 handle.cancel() 来取消计时器,而无需丢弃句柄。
计时器不会重复。每个计划中的计时器最多只会执行一次。
异步支持
RunLoop 可以用作未来执行器
RunLoop::current().spawn(async move ||{
RunLoop::current().wait(Duration::from_secs(10)).await;
println("After 10 second delay");
});
// or use crate::spawn variant:
spawn(async move ||{
RunLoop::current().wait(Duration::from_secs(10)).await;
println("After 10 second delay");
});
由于未来是在属于 RunLoop 的单个线程上执行的,因此它们不需要是 Send。
什么是主线程?
这在不同平台上略有不同。
- 在 iOS 和 macOS 上,它是应用程序启动时创建的第一个线程。它是
pthread_main_np()返回 1 的线程。 - 在 Linux 上,对于 RunLoop 的目的而言,主线程类似于 iOS 和 macOS 的第一个线程。
- 在 Android 上,存在主线程的概念(即
Looper.getMainLooper())。 - 在 Windows 上,主线程是应用程序启动时创建的第一个线程,类似于 macOS 和 iOS。如果您在不同的线程上创建窗口并泵送消息循环,
RunLoop::sender_for_main_thread()将不会按预期工作。
依赖关系
~0.9–15MB
~142K SLoC