Electron - 限制从主进程到渲染进程的消息流

Posted

技术标签:

【中文标题】Electron - 限制从主进程到渲染进程的消息流【英文标题】:Electron - throttle flow of messages from main to render process 【发布时间】:2022-01-15 04:49:27 【问题描述】:

我目前在接收从我的主进程到我的渲染器进程(在 Angular 中)的活动窗口的恒定流时遇到一些问题。我知道接收每秒更新会破坏我的应用程序,所以我试图使用 setTimeout 来限制它。但这仍然行不通。我该如何解决这个问题?

渲染器 - Angular 中的组件

  ipc: IpcRenderer | undefined | null;

  constructor(private electronService: ElectronService)  

  ngAfterViewInit(): void 
    this.getActiveWindow();
  

  getActiveWindow() 
    while(this.electronService.isElectronApp) 
      this.ipc = this.electronService.ipcRenderer;
      this.ipc.send('get-active-window');
      this.ipc.on('get-active-window-reply', (_event, reply) => 
        console.log(reply);
      );
    
  

ma​​in.js

const activeWindows = require('electron-active-window');

ipcMain.on('get-active-window', (_event, _arg) => 
  let i = 0;
  setTimeout(function () 
    activeWindows().getActiveWindow().then((result) => 
      win.webContents.send("get-active-window-reply", result)
    )
  , 10000 * i)
);

到目前为止,我已经尝试了以下方法,但这只会显示一次活动窗口。我想跟踪所有的变化:

渲染器 - Angular 中的组件

 ngOnInit(): void 
    this.getActiveWindow();
  

  getActiveWindow() 
    if(this.electronService.isElectronApp) 
      this.ipc = this.electronService.ipcRenderer;
      this.ipc.send('get-active-window');
      this.ipc.on('get-active-window-reply', (_event, reply) => 
        console.log(reply);
      );
    
  

ma​​in.js

ipcMain.on('get-active-window', (_event, _arg) => 
  activeWindows().getActiveWindow().then((result) => 
    win.webContents.send("get-active-window-reply", result)
  );
);

【问题讨论】:

这段代码有很多问题。您有一个 while 循环,它不断发送事件和注册处理程序。响应处理程序只是发送延迟响应。双方在本质上都有些异步。想想你当前的代码会发生什么以及你想要什么,然后尝试从那里重新工作。 @***soft 感谢您的回复。我已经更新了我的问题以显示我目前在哪里。第二次尝试似乎只获得一次窗口标题。我想让这个实时。我该如何解决这个问题? 【参考方案1】:

您只收到一次活动窗口,因为您只在ngOnInit 中请求它们一次。

所以在我看来,您目前有两种选择。

    您每隔几秒就向客户端请求一次信息 您让 Electron 应用程序通知客户端有关窗口的信息

选项 1:(仅解决方案 afaik)

render.component

import  interval  from 'rxjs';

...

getActiveWindow() 
  if(this.electronService.isElectronApp) 
    this.ipc = this.electronService.ipcRenderer;
    
    this.ipc.on('get-active-window-reply', (_event, reply) => 
      console.log(reply);
    );

    // A request directly to get "instant" feedback
    this.ipc.send('get-active-window');

    // You could also use setInterval but I prefer rxjs more ;)
    // Don't forget to unsubscribe in ngOnDestroy
    interval(2000).subscribe(() => 
      this.ipc.send('get-active-window');
    );
  

此解决方案会产生大量开销,因为您不需要每隔几秒更新活动窗口,因此我 推荐这个。

选项 2(推荐不起作用):

ma​​in.js

// Sends a message every time a BrowserWindow is created
app.on('browser-window-created', (event, window) => 
  this.sendActiveWindows();
);

// Respond to the client request
ipcMain.on('get-active-window', (_event, _arg) => 
   this.sendActiveWindows();
);

// Helper function
sendActiveWindows()
  activeWindows().getActiveWindow().then((result) => 
    win.webContents.send("get-active-window-reply", result)
  );


如果您还需要关闭窗口时的信息,您需要向BrowserWindow.on('closed',...)(更多here)添加一个侦听器,然后通知您的客户。

render.component.ts(仅添加 cmets)

getActiveWindow() 
  if(this.electronService.isElectronApp) 
    this.ipc = this.electronService.ipcRenderer;
    // Request the currently active windows, 
    // otherwise this info is missing until new window is created
    this.ipc.send('get-active-window');
    this.ipc.on('get-active-window-reply', (_event, reply) => 
      console.log(reply);
    );
  

此解决方案更合适,因为您的客户只会在窗口数量发生变化时收到通知,所以我推荐这个

更新

在聊天中澄清问题后,您不能使用选项 2,因为您想检测操作系统的活动窗口而不是 Electron 应用程序的活动窗口。 由于信息 选项 1 是唯一有效的解决方案这里

【讨论】:

getActiveWindow 应该可能从区间返回 Observable,否则很好的解决方案! 这取决于你 ;) 你也可以将订阅分配给 getActiveWindow 内部的一个变量,在这种情况下就没有必要了。谢谢:) 感谢@Batajus。我已经尝试了选项 2,但它似乎不起作用。我的 main.js 在pastebin.com/uV2b12Nm,我的组件代码在这里:pastebin.com/Ae4Bx0Pu。 选项 1 有效,但我在控制台中收到错误 (node:22168) MaxListenersExceededWarning: Possible EventEmitter memory leak detected. 11 get-active-window-reply listeners added to [EventEmitter]. Use emitter.setMaxListeners() to increase limit (Use electron --trace-warnings ...` 以显示警告的创建位置)`,所以这可能不是一个好主意. 初始化程序时它会选择新窗口标题,但当我切换到另一个程序时它不会选择它,例如 Telegram。

以上是关于Electron - 限制从主进程到渲染进程的消息流的主要内容,如果未能解决你的问题,请参考以下文章

在 Electron 中的两个渲染器进程之间直接通信

07.electron-(渲染进程和主进程)通信

你第一个Electron应用 | Electron in Action(中译)

08.electron-(渲染进程间的通信)

Electron 在渲染进程内可用的模块

不断地将事件从主进程传递到渲染器进程