关于electron在主进程阻塞的情况下ui会卡顿的问题

问题

在使用electron的过程中可能会出现这样的问题:

在我回调一个方法,比如child_process.spawn()的时候,我设计的等待动画不会出问题,在计算结束后等待动画也会结束,但是当我使用child_process.spawn()时就会出现动画进程不进行的情况。

参考Electron的主进程阻塞导致UI卡顿的问题这篇文章,我大概了解了electron的渲染方式:

实际的原因正是和其中的IPC有关,在chromium中,页面渲染时,UI进程需要和main process不断的进行sync IPC,若此时main process忙,则UI process就会在IPC时阻塞。

由于js是单线程的,在执行函数时如果遇到重cpu任务时就会造成主进程阻塞的情况。

 解决方法

那么该如何解决呢?我们可能会想既然异步的回调不会造成阻塞,为什么我们不都使用异步呢?

当接口是回调函数的时候当然没有问题,但是有些函数提供的api是同步的,如何解决这个问题?

这时候我们可以使用electron提供的window窗口功能,在需要执行的时候提前创建好一个透明窗口用来执行重cpu任务。当执行完成的时候通过ipc进行进程的通讯。

举个栗子:

//demo.js
function click() {
    const windowID = BrowserWindow.getFocusedWindow().id
    const invisPath = 'remote.html'
    let win = new BrowserWindow({
        width: 400,
        height: 400,
        show: false,
        webPreferences: {
            nodeIntegration: true
        }
    })
    win.loadFile(invisPath);

    win.webContents.on('did-finish-load', () => {
        var par;
        win.webContents.send('compute-vis', par, windowID);
    })
});

ipcRenderer.on('vis-computed', (event, output) => {
    console.log(output);
})
<!--remote.html-->
<html>
<script type="text/javascript">
    const ipc = require('electron').ipcRenderer
    const BrowserWindow = require('electron').remote.BrowserWindow
    const child_process = require('child_process');

    ipc.on('compute-vis', function (event, par, fromWindowId) {
        const result = visBuilding(par)
        const fromWindow = BrowserWindow.fromId(fromWindowId)
        fromWindow.webContents.send('vis-computed', result)
        window.close()
    })

    function visBuilding(par) {
        return par;
    }

</script>

</html>

 其中加载html的方法有两种:

mainWindow.loadURL(url.format({
  pathname: path.join(__dirname, 'index.html'),
  protocol: 'file:',
  slashes: true
}));
// or
invisPath=path.join(__dirname, 'index.html');
mainWindow.loadFile(invisPath);

这样就可以在子窗口中进行计算,并且回调结果了~

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章