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