上节继续,今天来研究tauri的事件(event),假设老板提了个需求,希望能实时监控cpu、内存等性能指标,你会怎么做?

思路1:

后端Rust暴露1个command,前端js不停去轮询(参考前文:tauri学习(3)-前端调用Rust代码),即传统的pull模型。

思路2:

后端不停对外喷数据,谁需要谁拿(类似发布-订阅模型)。

理论上二种思路都可以,今天讨论的是第2种,通过tauri的事件触发与监听来实现,而且event机制不仅仅限制于前端与后端通讯,还可以在前端-前端,后端与后端(多窗口应用,窗口之间)交换数据)。

一、准备工作:

1.1、如何在Rust中获取到CPU等实时监控指标?

perf_monitor = "0.2.0"

这里借助了perf_monitor这个开源第3方库,基本用法如下:

use perf_monitor::cpu::{processor_numbers, ProcessStat, ThreadStat};
use perf_monitor::fd::fd_count_cur;
use perf_monitor::io::get_process_io_stats;
use perf_monitor::mem::get_process_memory_info; /**
* 获取【cpu/内存/文件描述符数量/io】监控值
*/
fn monitor() -> Vec<String> {
// cpu
let core_num = processor_numbers().unwrap();
let mut stat_p = ProcessStat::cur().unwrap();
let mut stat_t = ThreadStat::cur().unwrap(); let usage_p = stat_p.cpu().unwrap() * 100f64;
let usage_t = stat_t.cpu().unwrap() * 100f64; let mut monitor_message: Vec<String> = Vec::with_capacity(3); monitor_message.push(format!(
"[CPU] core Number: {}, process usage: {:.2}%, current thread usage: {:.2}%",
core_num, usage_p, usage_t
)); // mem
let mem_info = get_process_memory_info().unwrap(); monitor_message.push(format!(
"[Memory] memory used: {} bytes, virtural memory used: {} bytes ",
mem_info.resident_set_size, mem_info.virtual_memory_size
)); // fd
let fd_num = fd_count_cur().unwrap();
monitor_message.push(format!("[FD] fd number: {}", fd_num));
// println!("[FD] fd number: {}", fd_num); // io
let io_stat = get_process_io_stats().unwrap();
monitor_message.push(format!(
"[IO] io-in: {} bytes, io-out: {} bytes",
io_stat.read_bytes, io_stat.write_bytes
)); monitor_message
}

  

1.2 设计事件的消息体

另:为了获取系统时间戳,从网上找了段代码

二、后端发送事件

2.1  发送事件代码

触发事件的核心就是emit方法(上图95行),事件名称可以随便取,但是要与前端监听指定的事件名保持一致。

说明一下:这里后端暴露了1个command,允许用户在前端通过按钮之类的,来触发后端吐数据(当然,大家也可以改成应用一启动,就直接开始监控cpu,无需前端触发)

另外,还演示了rust中的线程使用,创建1个独立线程来不停监控系统指标,然后1秒1次不停向外触发事件,这就带来另1个小问题,如果前端不停调用这个command,后端每次都会创建1个线程,容易引发其它问题,所以这里借助了1个全局变量来做辅助控制(当然,仅仅出于演示目的,应该有更优雅的做法)

2.2 暴露command

三、前端监听事件

import React from 'react';
import { invoke } from "@tauri-apps/api/tauri";
//监听事件
import { listen } from "@tauri-apps/api/event";
//用于格式化date
import format from 'date-fns/format'; import './index.css'; //用于取消监听
let unlisten: any = null //事件的消息体
interface Payload {
message: Array<string>,
timestamp: number,
} class Home extends React.Component { //初始状态
state = {
message: [],
timestamp: "",
time: ""
} //开始监听
start = () => {
invoke('init_process');
//防止重复监听
if (unlisten != null) {
console.log("already listen");
return;
} const start_listen = async () => {
//注意这里的my-event名称,要与后端保持一致
return await listen<Payload>('my-event', (event) => {
const { message, timestamp } = event.payload;
console.log("message:", message,
"timestamp:", timestamp, "time:",
format(new Date(timestamp), 'yyyy-MM-dd HH:mm:ss.SSS'));
this.setState({ message, timestamp, "time": format(new Date(timestamp), 'yyyy-MM-dd HH:mm:ss.SSS') }) });
};
unlisten = start_listen();
} //停止监听
stop = () => {
console.log("is_listening:", unlisten != null);
if (unlisten != null) {
unlisten.then((ok: any) => {
ok();
unlisten = null;
console.log("stop success");
}).catch((err: any) => {
console.log("stop fail", err);
})
}
} render() {
return (
<div>
<button onClick={() => this.start()}>start</button> 
<button onClick={() => this.stop()}>stop</button><br />
<h4>{this.state.time}</h4>
<div >
{
this.state.message.map((item, index) => {
return (<span className="monitor" key={`${this.state.timestamp}_${index}`}> {item}</span>)
})
}
</div>
</div >
)
}
} export default Home

核心部分都加了注释,应该不难看懂,运行效果如下:

代码示例:

https://github.com/yjmyzz/tauri-visited-solution/tree/event

参考文章:

https://tauri.app/v1/guides/features/events

tauri学习(7)-事件(event)的更多相关文章

  1. Lite OS学习之事件EVENT

    1. Lite OS的事件EVENT,就是一个任务向另外一个任务通知事件的,不能数据传输.看下有的函数,实际比较复杂 2. 具体还是看编程,先全局结构体整个事件变量 /*事件控制结构体*/ EVENT ...

  2. 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果

    学习笔记---Javascript事件Event.IE浏览器下的拖拽效果     1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...

  3. Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群

    Redis总结(五)缓存雪崩和缓存穿透等问题   前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...

  4. libevent源码学习(9):事件event

    目录在event之前需要知道的event_baseevent结构体创建/注册一个event向event_base中添加一个event设置event的优先级激活一个event删除一个event获取指定e ...

  5. 经典线程同步 事件Event

    阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...

  6. 多线程面试题系列(6):经典线程同步 事件Event

    上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...

  7. 自定义事件——Event和CustomEvent

    之前在学习自定义事件时,在MDN的Event.initEvent()页面顶端有写:该特性已从Web标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性. 作 ...

  8. 详解 Solidity 事件Event - 完全搞懂事件的使用

    很多同学对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用? 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊. ...

  9. 秒杀多线程第六篇 经典线程同步 事件Event

    原文地址:http://blog.csdn.net/morewindows/article/details/7445233 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的“线程所有权” ...

  10. pythonl练习笔记——threading线程中的事件Event

    1 事件Event 使用方法:e = threading.Event() Event对象主要用于线程间通信,确切地说是用于主线程控制其他线程的执行. Event事件提供了三个方法:wait等待.cle ...

随机推荐

  1. Dubbo实战:四步实现注册中心平滑迁移原创

      写在前面 如题,这是一个真实存在的业务场景.在微服务体系的迭代过程中,会存在注册中心的切换,典型如从zookeeper迁移到nacos. 最近面试中,经常会用该场景来考察候选人(涉及RPC.分布式 ...

  2. 40.8K star!让AI帮你读懂整个互联网:Crawl4AI开源爬虫工具深度解析

    嗨,大家好,我是小华同学,关注我们获得"最新.最全.最优质"开源项目和高效工作学习方法 Crawl4AI 是2025年GitHub上最受瞩目的开源网络爬虫工具,专为AI时代设计.它 ...

  3. 活动箭线的"总时差和专用时差"

    总时差:后大 - 前小 - 作业时间 专用时差:后小 - 前大 - 作业时间

  4. AI模型的回调能力的理解和实现

    前言 BigTall最近把RAG和Agent的原理想通了,对于"一切都是提示词"的理解又更多了一些.本文把我的理解大致整理了一下,给出BigTall自己的一个实验.希望能够对大家有 ...

  5. 张高兴的大模型开发实战:(六)在 LangGraph 中使用 MCP 协议

    目录 什么是 MCP 协议 MCP 协议与 API 调用的区别 MCP 协议的连接方式 SSE(Server-Sent Events) stdio(标准输入输出) 在 LangGraph 中使用 MC ...

  6. ESP实现Web服务器

    ESP实现Web服务器 典型的基于 ESP32 的静态网页与图片嵌入展示的 本地 Web Server(AP 模式)项目 项目功能概述 ESP32 创建一个 Wi-Fi 热点,启动一个 HTTP We ...

  7. Python实现http接口请求数据后,往RabbitMQ里面插入数据

    python实现http接口请求数据服务后,往RABBITmq里面插入数据 import time import requests import pika import datetime base_u ...

  8. Java 17 java.util.HashSet 类源码分析

    在绍了 Map 集合的一种典型实现 HashMap之后 ,我们知道,自Java 8起HashMap 是由数组+但链表+红黑树构成,相对于早期版本的 HashMap 实现,新增了红黑树作为底层数据结构, ...

  9. JWT令牌如何在FastAPI中实现安全又高效的生成与验证?

    title: JWT令牌如何在FastAPI中实现安全又高效的生成与验证? date: 2025/06/10 09:02:35 updated: 2025/06/10 09:02:35 author: ...

  10. java练习题之String字符串

    1 编写程序将"jdk" 全部变成大写  并输出到屏幕 截取"DK"并输出到屏幕 1 package com.lv.study.am.first; 2 3 pu ...