current position:Home>Electronic multi process solution interface Caton

Electronic multi process solution interface Caton

2021-08-27 06:10:57 Sword teacher_

This article was first published on the official account 【 An old yard farmer 】

Because of the company's business needs , Recently participated in a company's desktop application . The technology stack is electron+react, The interface part mainly uses antd.

There is a problem in the development process : There is a very time-consuming task , When the task is on , It will cause the whole application interface to get stuck , The interface operation can only be performed after the task execution is completed . Let's talk about it today electron Processing methods of intensive tasks in .

Caton's reason

because electron The app uses js As a development language , and js It's single threaded , therefore electron There is no multithreading , But it allows multiple processes . stay electron It is divided into main process and rendering process , The main process is in main File control , At the same time, this file is also responsible for controlling the application life cycle .( notes :main The file in package.json In the configuration file main Field ) Each window is a rendering process, which is what we call UI process . After research, we found that , The application interface is stuck because the task consumes more resources , This will cause the current rendering process to get stuck .

How to avoid UI Carton

About electron Application performance optimization ,electron The official document of gives the following suggestions : whenever Node.js Core module ( Such as fs) Provide a synchronous version or an asynchronous version , You should use asynchronous and non blocking variables

Avoid using synchronization whenever possible IPC and remote modular , Use remote It's very easy to block the module unknowingly UI Threads

For long-term occupation CPU Heavy tasks , You can move them to BrowserWindow, Generate a dedicated process .( That is, create a new window )

Specific solutions

Based on official documents , I used to create a new hidden BrowserWindow The way , Put time-consuming tasks in a new window . Because of each BrowserWindow Is a separate rendering process , Therefore, this method can avoid interface jamming . And task processing progress , Hidden rendering process ( After use " Task progress " Instead of ) Can pass IPC The way of communication tells the main process , The main process then notifies the current rendering process . For convenience, you can also use... In the current rendering process remote.ipcMain.on() To communicate with the task process .

The core code is as follows :

Listen during the current rendering process , Because there is no communication between the rendering process and the rendering process , So it can be used remote.ipcMain Get the main process object to listen

// The current rendering process 
import { remote } from 'electron'
import React, { useState, useEffect, useRef } from 'react'


const win = useRef()

useEffect(() => {
    return () => {
      closeArchiveRenderer()
    }
  }, [])

// Start task 
function begain() {
    listenIpcRenderer()
    createNewWindow()
}

// Create hide window
function createNewWindow() {
    let win.current = new remote.BrowserWindow({
      width: 500,
      height: 500,
      show: false,
      webPreferences: {
        nodeIntegration: true,
        contextIsolation: false,
        enableRemoteModule: true,
      },
    })
    win.current.loadURL('xxxxxx')
}

//ipc Communication monitoring 
function listenIpcRenderer() {
    remote.ipcMain.on('window-load-success', (event, arg) => {
      console.log(arg)
      if (arg) {
        event.reply('begain-task', {
            //tag Mark the task type 
          tag: 'xxx', 
          // Data passed to the task process 
          dataSource: dataSource
        })
      }
    })

remote.ipcMain.on('change-task-status', (event, arg) => {
      console.log(arg)
      if (arg.error) {
        console.log(arg.error)
        return
      }
      if (arg.status === 2) {
        // State processing 
      }
    })

remote.ipcMain.on('task-complete', (event, arg) => {
    // Task to complete 
    // Close the process , Remove monitor , It can be placed in a suitable place as needed 
    closeArchiveRenderer()
    })
}


// Close the process at the right time , And remove the listener 
function closeArchiveRenderer() {
    if (win.current) {
      win.current.close()
      win.current = null
    }
    remote.ipcMain.removeAllListeners()
  }

 Copy code 

This is required in task specific processes

//  Task progress , The current window handles the hidden state 
import { ipcRenderer } from 'electron'

useEffect(() => {
    ipcRenderer.on('begain-task', (event, arg) => {
      //  according to tag Judge the type of task 
      if (arg.tag === 'xxxx') {
        console.log(arg.dataSource)
        // Task processing TODO
        xxxx()
        // The following code can be placed in the right place as needed 
        // If the processing state changes, send a change notification 
        ipcRenderer.send('change-task-status', data)

        // If the task is done , Then send a completion notice 
        ipcRenderer.send('task-complete', data)
      }
    })

    ipcRenderer.send('window-load-success', true)
    return () => {
      ipcRenderer.removeAllListeners()
    }
  }, [])
 Copy code 

Official account 【 An old yard farmer 】, More high-quality technical content is waiting for you

Original address

copyright notice
author[Sword teacher_],Please bring the original link to reprint, thank you.
https://en.qdmana.com/2021/08/20210827061054819j.html

Random recommended