Rust异步定时器库async-timer的使用:高效、轻量级的跨平台定时任务调度解决方案

Rust异步定时器库async-timer的使用:高效、轻量级的跨平台定时任务调度解决方案

async-timer简介

async-timer是Rust的异步计时器库,提供定时任务调度功能。它具有以下特点:

  • 支持no_std环境
  • 最小Rust版本要求:1.36
  • 跨平台支持

定时任务(Timed)

async fn job() {
}

async fn do_job() {
    let work = unsafe {
        async_timer::Timed::platform_new_unchecked(job(), core::time::Duration::from_secs(1))
    };

    match work.await {
        Ok(_) => println!("I'm done!"),
        // 可以通过轮询`expired`来重试
        Err(expired) => println!("Job expired: {}", expired),
    }
}

间隔任务(Interval)

async fn job() {
}

async fn do_a_while() {
    let mut times: u8 = 0;
    let mut interval = async_timer::Interval::platform_new(core::time::Duration::from_secs(1));

    while times < 5 {
        job().await;
        interval.as_mut().await;
        times += 1;
    }
}

Q&A

Q: 什么时候会支持async/await?

A: 当async/await支持no_std环境时

完整示例代码

use async_timer::{Timed, Interval};
use std::time::Duration;
use tokio; // 需要tokio或其他异步运行时

#[tokio::main]
async fn main() {
    // 定时任务示例
    println!("=== 定时任务示例 ===");
    timed_example().await;
    
    // 间隔任务示例
    println!("=== 间隔任务示例 ===");
    interval_example().await;
}

async fn timed_example() {
    async fn task() {
        println!("定时任务执行中...");
    }
    
    let work = unsafe {
        Timed::platform_new_unchecked(task(), Duration::from_secs(2))
    };
    
    match work.await {
        Ok(_) => println!("定时任务完成!"),
        Err(e) => println!("定时任务失败: {}", e),
    }
}

async fn interval_example() {
    async fn periodic_task() {
        println!("周期性任务执行...");
    }
    
    let mut counter = 0;
    let mut interval = Interval::platform_new(Duration::from_secs(1));
    
    while counter < 5 {
        periodic_task().await;
        interval.as_mut().await;
        counter += 1;
    }
    
    println!("已完成5次周期性任务");
}

要使用这个库,需要在Cargo.toml中添加以下依赖:

[dependencies]
async-timer = "0.7.4"
tokio = { version = "1", features = ["full"] } # 或其他异步运行时

这个库特别适合需要轻量级、跨平台定时任务调用的异步Rust应用场景。


1 回复

Rust异步定时器库async-timer的使用指南

概述

async-timer是一个高效、轻量级的跨平台异步定时器库,专为Rust的异步生态系统设计。它提供了简单的API来创建和管理定时任务,适用于需要延迟执行或周期性任务的异步应用场景。

主要特性

  • 跨平台支持(Linux/macOS/Windows)
  • 零依赖(仅使用标准库和futures)
  • 线程安全(可在多线程环境中使用)
  • 精确的定时控制
  • 与async/await语法无缝集成

安装

在Cargo.toml中添加依赖:

[dependencies]
async-timer = "1.0"

基本使用方法

1. 一次性定时器(Oneshot Timer)

use async_timer::oneshot::Oneshot;
use std::time::Duration;

#[tokio::main]
async fn main() {
    // 创建一个3秒后触发的定时器
    let timer = Oneshot::new(Duration::from_secs(3));
    
    println!("等待定时器...");
    timer.await;
    println!("3秒已过!");
}

2. 周期性定时器(Interval Timer)

use async_timer::interval::Interval;
use std::time::Duration;

#[tokio::main]
async fn main() {
    // 创建一个每1秒触发一次的定时器
    let mut interval = Interval::new(Duration::from_secs(1));
    
    for i in 1..=5 {
        interval.next().await;
        println!("第 {} 次触发", i);
    }
}

3. 取消定时器

use async_timer::oneshot::Oneshot;
use std::time::Duration;

#[tokio::main]
async fn main() {
    let timer = Oneshot::new(Duration::from_secs(5));
    
    tokio::spawn(async move {
        tokio::time::sleep(Duration::from_secs(2).await;
        println!("取消定时器");
        timer.cancel();
    });
    
    match timer.await {
        Ok(()) => println!("定时器正常完成"),
        Err(_) => println!("定时器被取消"),
    }
}

高级用法

与select!宏配合使用

use async_timer::oneshot::Oneshot;
use std::time::Duration;

#[tokio::main]
async fn main() {
    let timer = Oneshot::new(Duration::from_secs(3));
    let timeout = tokio::time::sleep(Duration::from_secs(5));
    
    tokio::select! {
        _ = timer => println!("定时器先触发"),
        _ = timeout => println!("超时先触发"),
    }
}

动态调整定时器

use async_timer::interval::Interval;
use std::time::Duration;

#[tokio::main]
async fn main() {
    let mut interval = Interval::new(Duration::from_secs(1));
    
    for i in 1..=10 {
        interval.next().await;
        println!("触发 {}", i);
        
        // 每5次后增加间隔时间
        if i % 5 == 0 {
            interval.set_period(Duration::from_secs(2));
            println!("间隔时间增加到2秒");
        }
    }
}

完整示例demo

下面是一个结合了多种特性的完整示例:

use async_timer::{oneshot::Oneshot, interval::Interval};
use std::time::Duration;

#[tokio::main]
async fn main() {
    // 示例1:一次性定时器
    println!("--- 一次性定时器示例 ---");
    let oneshot = Oneshot::new(Duration::from_secs(2));
    oneshot.await;
    println!("一次性定时器触发!\n");

    // 示例2:周期性定时器
    println!("--- 周期性定时器示例 ---");
    let mut interval = Interval::new(Duration::from_secs(1));
    for i in 1..=3 {
        interval.next().await;
        println!("周期性触发 {}", i);
    }

    // 示例3:取消定时器
    println!("\n--- 取消定时器示例 ---");
    let cancel_timer = Oneshot::new(Duration::from_secs(3));
    let cancel_handle = tokio::spawn(async move {
        tokio::time::sleep(Duration::from_secs(1)).await;
        println!("尝试取消定时器...");
        cancel_timer.cancel();
    });

    match cancel_timer.await {
        Ok(()) => println!("定时器正常完成"),
        Err(_) => println!("定时器已被取消"),
    }
    cancel_handle.await.unwrap();

    // 示例4:动态调整定时器
    println!("\n--- 动态调整定时器示例 ---");
    let mut dynamic_interval = Interval::new(Duration::from_millis(500));
    for i in 1..=6 {
        dynamic_interval.next().await;
        println!("动态触发 {}", i);
        
        if i == 3 {
            dynamic_interval.set_period(Duration::from_secs(1));
            println!("已将间隔调整为1秒");
        }
    }

    // 示例5:与select!宏配合使用
    println!("\n--- select!宏示例 ---");
    let timer1 = Oneshot::new(Duration::from_secs(2));
    let timer2 = Oneshot::new(Duration::from_secs(3));
    
    tokio::select! {
        _ = timer1 => println!("定时器1先触发"),
        _ = timer2 => println!("定时器2先触发"),
    }
}

性能建议

  1. 对于大量定时器场景,考虑使用单个定时器任务配合任务队列
  2. 避免创建非常短间隔(<10ms)的定时器,这可能导致不精确
  3. 对于高精度需求,考虑平台特定的定时器实现

注意事项

  • 定时器精度受系统调度器影响
  • 取消定时器后,等待该定时器的所有future都会立即返回错误
  • 在多线程环境中使用时,确保正确同步

async-timer是构建异步定时任务的轻量级解决方案,特别适合需要跨平台支持的Rust异步应用。

回到顶部