首页 > 其他分享 >tauri学习(7)-事件(event)

tauri学习(7)-事件(event)

时间:2022-08-28 18:33:54浏览次数:77  
标签:学习 monitor tauri let io message 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

标签:学习,monitor,tauri,let,io,message,event
From: https://www.cnblogs.com/yjmyzz/p/event-with-tauri.html

相关文章

  • 享元模式学习笔记
    引用微信读书——游戏编程模式前言“使用共享以高效地支持大量的细粒度对象。”迷雾升起,一片雄伟、古老而茂盛的森林在眼前展现。数不尽的远古铁杉迎面扑来,宛如一座......
  • 流行的机器学习优化算法
    流行的机器学习优化算法Photoby康尼施耐德on不飞溅机器学习中的优化是在给定一组输入的情况下找到正确预测的迭代过程。在每次迭代中,目标是减少预测值与实际值之......
  • vue——全局事件总线(GlobalEventBus)
    一.什么是全局事件总线?1.一种组件间通信的方式,适用于任意组件间通信。是根据VueComponent.prototype.__proto__=Vue.prototype的原理来进行全局引用二.全局事件总线......
  • Fiddler学习笔记--基础了解(7)
    首次打开Fiddler默认是不会捕获HTTPS,需要配置后方可捕获HTTPStools--FiddlerOptions--HTTPS,然后将界面选项全部勾选上如果我们有远程监控需求,需要切换值connections,......
  • Java开发学习(二十七)----SpringMVC之Rest风格解析及快速开发
    一、REST简介REST(RepresentationalStateTransfer),表现形式状态转换,它是一种软件架构风格当我们想表示一个网络资源的时候,可以使用两种方式:传统风格资源描述形式......
  • delphi TdxBarManager学习笔记
    一.WholeRow工具显示模式WholeRow:true工具栏单独在一行显示,不管你有几个内含元素默认为WholeRow:false,即同一行内可以排列多个工具栏,像下图就同时排列了三个工具栏......
  • Google C++ Style Guide 学习
    目录参考参考http://home.ustc.edu.cn/~hqp/RootClass/AddFiles2/GoogleC++StyleGuide.pdfhttps://zh-google-styleguide.readthedocs.io/en/latest/google-cpp-styl......
  • PyTorch Geometric(pyg)学习
    参考2个链接: 第十六课.Pytorch-geometric入门(一)_tzc_fly的博客-CSDN博客_pytorch-geometric 第十七课.Pytorch-geometric入门(二)_tzc_fly的博客-CSDN博客......
  • spring学习
    pringBoot自动装配原理及分析通过注解@SpringBootApplication=>@EnableAutoConfiguration=>@Import({AutoConfigurationImportSelector.class})实现自动装配2)AutoConfigu......
  • cmake的install命令学习
    转自:https://blog.csdn.net/qq_38410730/article/details/1028374011.install命令install用于指定在安装时运行的规则。它可以用来安装很多内容,可以包括目标二进制、动态......