tauri学习(7)-事件(event)
接上节继续,今天来研究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)的更多相关文章
- Lite OS学习之事件EVENT
1. Lite OS的事件EVENT,就是一个任务向另外一个任务通知事件的,不能数据传输.看下有的函数,实际比较复杂 2. 具体还是看编程,先全局结构体整个事件变量 /*事件控制结构体*/ EVENT ...
- 学习笔记---Javascript事件Event、IE浏览器下的拖拽效果
学习笔记---Javascript事件Event.IE浏览器下的拖拽效果 1. 关于event常用属性有returnValue(是否允许事件处理继续进行, false为停止继续操作).srcE ...
- Redis总结(五)缓存雪崩和缓存穿透等问题 Web API系列(三)统一异常处理 C#总结(一)AutoResetEvent的使用介绍(用AutoResetEvent实现同步) C#总结(二)事件Event 介绍总结 C#总结(三)DataGridView增加全选列 Web API系列(二)接口安全和参数校验 RabbitMQ学习系列(六): RabbitMQ 高可用集群
Redis总结(五)缓存雪崩和缓存穿透等问题 前面讲过一些redis 缓存的使用和数据持久化.感兴趣的朋友可以看看之前的文章,http://www.cnblogs.com/zhangweizhon ...
- libevent源码学习(9):事件event
目录在event之前需要知道的event_baseevent结构体创建/注册一个event向event_base中添加一个event设置event的优先级激活一个event删除一个event获取指定e ...
- 经典线程同步 事件Event
阅读本篇之前推荐阅读以下姊妹篇: <秒杀多线程第四篇 一个经典的多线程同步问题> <秒杀多线程第五篇 经典线程同步关键段CS> 上一篇中使用关键段来解决经典的多线程同步互斥问题 ...
- 多线程面试题系列(6):经典线程同步 事件Event
上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的"线程所有权"特性所以关键段只能用于线程的互斥而不能用于同步.本篇介绍用事件Event来尝试解决这个线程同步问题.首先 ...
- 自定义事件——Event和CustomEvent
之前在学习自定义事件时,在MDN的Event.initEvent()页面顶端有写:该特性已从Web标准中删除,虽然一些浏览器目前仍然支持它,但也许会在未来的某个时间停止支持,请尽量不要使用该特性. 作 ...
- 详解 Solidity 事件Event - 完全搞懂事件的使用
很多同学对Solidity 中的Event有疑问,这篇文章就来详细的看看Solidity 中Event到底有什么用? 写在前面 Solidity 是以太坊智能合约编程语言,阅读本文前,你应该对以太坊. ...
- 秒杀多线程第六篇 经典线程同步 事件Event
原文地址:http://blog.csdn.net/morewindows/article/details/7445233 上一篇中使用关键段来解决经典的多线程同步互斥问题,由于关键段的“线程所有权” ...
- pythonl练习笔记——threading线程中的事件Event
1 事件Event 使用方法:e = threading.Event() Event对象主要用于线程间通信,确切地说是用于主线程控制其他线程的执行. Event事件提供了三个方法:wait等待.cle ...
随机推荐
- 我的get请求为什么没有乱码??
请求的方式有GET和POST两种放方式.这里主要说明GET请求的中文问题. 傻傻的我以为GET不能提交中文,需要改编码,但是我错了.改了编码反而乱码了??? 原因: Tomcat8 以后tomcat的 ...
- 基于主成分分析(PCA)的数据降维
一.概述 主成分分析(Principal Component Analysis,PCA)是一种用于数据降维的方法,其核心目标是在尽可能保留原始数据信息的前提下,将高维数据映射到低维空间.该算法基于 ...
- k8s入门操作
kubectl -->apiserver 管理工具 管理k8s集群 增删改查node kubectl get service/node/replicaset/deployment/statefu ...
- VMware workstation 部署微软MDT系统
一.环境准备 1. VMware Workstation 虚拟机配置 新建虚拟机 类型:Microsoft Windows Server 2022 Standard 内存:4GB+ 硬盘:100GB( ...
- 基于libwchnet&Mbedtls实现HTTPS
引言: 本文将介绍使用CH32V307VCT6以及官方协议栈(libwchnet)搭配Mbedtls作为客户端通过HTTPS访问百度并获取百度首页数据. 一.HTTPS概述与SSL/TSL简介 HTT ...
- git命令--拉取代码和切换分支
git一般有很多分支,我们clone到本地的代码都是master分支,那么如何切换到其它分支呢?本文介绍主要操作流程和命令,包括拉取仓库代码.查看分支和切换分支,至于如何提交代码,需要的童鞋自己查 ...
- 20244104陈思淼 《Python程序设计》实验三报告
课程:<Python程序设计> 班级:2441 姓名:陈思淼 学号:20244104 实验教师:王志强 实验日期:20254月20日 必修/选修: 公选课 1.实验内容 创建服务端和客户端 ...
- HarmonyOS运动开发:打造你的专属运动节拍器
##鸿蒙核心技术##运动开发##Media Kit(媒体服务)# 前言 在运动过程中,保持稳定的节奏对于提升运动效果至关重要.无论是跑步.骑自行车还是进行高强度间歇训练(HIIT),一个精准的节拍器都 ...
- kubernetes配置glusterfs动态存储
GlusterFS分布式文件系统 一.简单介绍 分布式存储按其存储接口分为三种:文件存储.块存储.对象存储 文件存储 通常支持POSIX接口(如glusterFS,但GFS.HDFS是非POSIX接口 ...
- ChatMoney,你的就业指导明灯
本文由 ChatMoney团队出品 介绍说明 Hey!亲爱的小伙伴们,今天我要给大家带来一个职场利器--AI就业指导机器人! 在这个充满变数的职场江湖,找到一份既能养家糊口又能实现自我价值的工作是多么 ...