[Upscayl图像增强] Electron主进程命令 | 进程间通信IPC
第三章:Electron主进程命令
欢迎回来🐻❄️
在第一章:渲染器用户界面(前端)中,我们探索了您与之交互的按钮和菜单。然后在第二章:AI模型中,我们了解了让您的图像看起来更棒的"智能"。您选择图像,选择模型,然后点击"Upscayl"。
但是在点击按钮和图像实际被放大之间发生了什么?谁将您的选择从用户界面转化为计算机上的操作?这就是Electron主进程命令的作用
Electron主进程命令解决了什么问题?
将Upscayl想象成一个繁忙的餐厅。渲染器用户界面(前端)是友好的服务员,接受您的订单(“使用’remacri-4x’模型放大这张图像”)。
AI模型是专门的食谱。但谁去厨房获取食材,告诉实际的厨师该做什么,并确保一切顺利进行?那就是Electron主进程。
Electron主进程命令解决的核心问题是弥合基于web的用户界面与计算机操作系统之间的鸿沟。普通的网页(如前端)不能直接:
- 在计算机上打开文件选择窗口。
- 将文件保存到特定文件夹。
- 运行强大的外部程序。
- 发送系统通知。
主进程充当整个Upscayl应用程序的"控制中心"或"指挥"。它是Upscayl中唯一能够直接与计算机系统对话的部分,确保应用程序能够执行所有繁重的工作,并与操作系统和其他工具正确交互。
核心用例:协调图像放大
让我们使用主要示例:放大单张图像。
当:
- 在渲染器用户界面(前端)中点击"选择图像"。
- 从计算机中选择图像文件。
- 选择一个AI模型(如
remacri-4x
)。 - 点击大的"Upscayl"按钮。
Electron主进程协调整个操作。它接收您的指令,准备所有必要的信息,启动实际的放大工作,监控其进度,并处理保存结果。
什么是Electron主进程?
要理解主进程,让我们简要回顾一下Upscayl构建工具Electron。Electron应用程序通常有两种主要类型的进程:
- 渲染器进程(服务员):这是渲染器用户界面(前端)所在的地方。它像一个网页浏览器页面,非常适合显示视觉效果和处理点击,但对计算机系统的访问有限。
- 主进程(厨师/经理):这是应用程序的"大脑"。它运行一个Node.js环境,这意味着它可以完全访问计算机的操作系统。它管理应用程序的窗口,处理系统事件,并执行渲染器进程无法完成的所有"繁重"任务。整个应用程序只有一个主进程。
Electron主进程命令只是渲染器进程发送给主进程的特定指令或"消息",要求它执行系统级任务。
主进程如何与前端通信
由于渲染器和主进程是分开的,它们需要一种相互通信的方式。这是通过**进程间通信(IPC)**实现的。
IPC: https://github.com/lvy010/linux-core/tree/main/ipc_test
想象服务员(前端)将您的订单写在票上并交给厨师(主进程)。票上有清晰的"命令"和所有细节。
在Upscayl中,这些"命令"使用特定名称定义:
// common/electron-commands.ts(简化版)
const ELECTRON_COMMANDS = {SELECT_FILE: "选择文件", // 命令主进程打开文件对话框UPSCAYL: "放大图像", // 命令主进程开始放大UPSCAYL_DONE: "放大完成", // 主进程向前端发送的消息UPSCAYL_PROGRESS: "从主进程发送进度到渲染器", // 进度更新STOP: "停止当前操作", // 停止放大的命令// ... 许多其他命令 ...
} as const;export { ELECTRON_COMMANDS };
这个ELECTRON_COMMANDS
列表就像一个共享字典。渲染器用户界面(前端)和主进程都知道这些名称,确保它们在发送消息时相互理解。
当渲染器用户界面(前端)想要完成某件事时,它使用这些命令名称发送消息。当主进程完成任务或有更新时,它使用命令名称向前端发送消息。
放大命令的旅程
让我们追踪当点击"Upscayl"按钮时发生的情况,从用户界面到实际工作完成:
以下是图表的逐步解释:
- 用户交互:您(
用户
)在渲染器用户界面(前端)中点击"Upscayl"按钮。 - 收集信息:
RendererUI
收集您提供的所有信息:原始图像的位置、选择的AI模型、期望的放大倍数(如4x)和其他设置。 - 发送命令:
RendererUI
将这些信息打包成"消息",并使用UPSCAYL
命令发送给Electron主进程
。这条消息包含主进程需要知道的一切。 - 主进程准备:
MainProcess
接收UPSCAYL
命令。然后执行系统级任务:确定正确的输出文件夹,创建唯一的文件名,并准备运行实际放大程序所需的所有参数。 - 启动放大二进制文件:
MainProcess
然后启动一个独立的强大程序,称为放大二进制文件(upscayl-bin
)。它将所有准备好的参数(图像路径、模型路径、输出路径、放大倍数等)传递给这个二进制文件。 - 放大工作:
放大二进制文件
开始使用选定的AI模型进行实际的、计算密集的图像增强工作。 - 进度更新:当
放大二进制文件
工作时,它向MainProcess
发送进度更新。 - 转发进度:
MainProcess
接收这些进度更新,然后使用UPSCAYL_PROGRESS
命令将它们发送回RendererUI
。这就是看到进度条移动的方式! - 完成:一旦
放大二进制文件
完成,它告诉MainProcess
它已完成,并提供新放大图像的路径。 - 最终通知和显示:
MainProcess
发送最终的UPSCAYL_DONE
命令,包括放大图像的路径,返回给RendererUI
。RendererUI
然后显示惊人的结果,并可能向您显示系统通知。
这整个序列由主进程协调,充当中央指挥。
深入代码:如何处理命令
让我们看一些简化的代码片段,看看这些命令在Upscayl中是如何实际注册和处理的
1. 在主进程中注册命令
主进程需要知道当接收到特定命令时该做什么。
这就像餐厅经理将任务分配给员工。在Electron中,这是使用ipcMain.on
(对于仅执行操作的命令)或ipcMain.handle
(对于返回值的命令)完成的。
// electron/index.ts(简化版)
import { app, ipcMain } from "electron";
import { ELECTRON_COMMANDS } from "../common/electron-commands";
import selectFile from "./commands/select-file"; // 选择文件的命令处理程序
import imageUpscayl from "./commands/image-upscayl"; // 放大命令的处理程序
import stop from "./commands/stop"; // 停止任务的命令处理程序app.on("ready", async () => {// ... 其他应用程序设置 ...// 注册命令:当前端发送SELECT_FILE时,运行'selectFile'函数ipcMain.handle(ELECTRON_COMMANDS.SELECT_FILE, selectFile);// 注册命令:当前端发送UPSCAYL时,运行'imageUpscayl'函数ipcMain.on(ELECTRON_COMMANDS.UPSCAYL, imageUpscayl);// 注册命令:当前端发送STOP时,运行'stop'函数ipcMain.on(ELECTRON_COMMANDS.STOP, stop);
});
这个electron/index.ts
文件是主进程的入口点。它是应用程序开始监听来自渲染器用户界面(前端)的所有不同命令的地方。每个ipcMain.handle
或ipcMain.on
行将一个特定的ELECTRON_COMMANDS
消息连接到一个将处理它的函数(如selectFile
或imageUpscayl
)。
2. 处理"选择文件"命令
当您在渲染器用户界面(前端)中点击"选择图像"时,该组件发送一个SELECT_FILE
命令。以下是主进程接收它时的操作:
// electron/commands/select-file.ts(简化版)
import { dialog } from "electron";
import { setSavedImagePath } from "../utils/config-variables";
import logit from "../utils/logit"; // 记录消息的辅助工具const selectFile = async () => {// 在计算机上打开一个本地文件选择对话框const { canceled, filePaths } = await dialog.showOpenDialog({properties: ["openFile"],title: "选择图像",filters: [{ name: "图像", extensions: ["png", "jpg", "jpeg"] }],});if (canceled) {logit("🚫 文件选择已取消");return null; // 如果用户取消,返回null} else {setSavedImagePath(filePaths[0]); // 保存路径以备下次使用logit("📄 选择的文件路径: ", filePaths[0]);return filePaths[0]; // 将选择的文件路径发送回前端}
};export default selectFile;
这个selectFile
函数非常重要,因为它允许Upscayl与计算机的文件系统交互。当这个函数运行时,它使用dialog.showOpenDialog
显示熟悉的"打开文件"窗口。如果您选择一个文件,它的路径(如C:/Users/您的名字/图片/image.jpg
)将返回给渲染器用户界面(前端),然后显示图像。
3. 处理"放大图像"命令
这是最重要的一个!当发送UPSCAYL
命令时,主进程中的imageUpscayl
函数接管:
// electron/commands/image-upscayl.ts(简化版)
import { modelsPath } from "../utils/get-resource-paths"; // 内置AI模型的路径
import { ELECTRON_COMMANDS } from "../../common/electron-commands";
import { setChildProcesses } from "../utils/config-variables";
import { getSingleImageArguments } from "../utils/get-arguments"; // 构建参数的辅助工具
import { spawnUpscayl } from "../utils/spawn-upscayl"; // 运行放大程序的辅助工具
import { getMainWindow } from "../main-window";
import logit from "../utils/logit";const imageUpscayl = async (event, payload) => {const mainWindow = getMainWindow(); // 获取主窗口的引用if (!mainWindow) return;// 从前端传递的payload中提取所有设置const model = payload.model;const imagePath = payload.imagePath;const outputPath = payload.outputPath;const scale = payload.scale;// ... 以及payload中的许多其他设置 ...// 为放大二进制文件构建特定的命令行参数const args = getSingleImageArguments({inputDir: imagePath,model: model,modelsPath: modelsPath, // 提供AI模型文件的路径outFile: outputPath,scale: scale,// ... 所有其他参数 ...});// 启动实际的放大程序([放大二进制文件(`upscayl-bin`)])const upscaylProcess = spawnUpscayl(args, logit);setChildProcesses(upscaylProcess); // 跟踪这个正在运行的进程// 监听放大二进制文件的进度更新upscaylProcess.process.stderr.on("data", (data: string) => {// 将进度百分比发送回前端mainWindow.webContents.send(ELECTRON_COMMANDS.UPSCAYL_PROGRESS,data.toString(),);});// 监听放大程序何时完成upscaylProcess.process.on("close", async () => {logit("💯 放大完成");// 通知前端放大已完成mainWindow.webContents.send(ELECTRON_COMMANDS.UPSCAYL_DONE,outputPath,);// ... 执行最终任务,如显示通知 ...});
};export default imageUpscayl;
这个imageUpscayl
函数是放大过程的终极"指挥"!
- 它接收
payload
(来自渲染器用户界面(前端)的所有选择的集合)。 - 然后使用辅助函数(
getSingleImageArguments
)构建外部放大二进制文件(upscayl-bin
)运行所需的精确命令。 spawnUpscayl
函数然后执行放大二进制文件(upscayl-bin
)作为一个独立的程序。- 关键的是,它为这个运行的程序附加"监听器"(
.on("data")
和.on("close")
)。这使得MainProcess
能够持续监控进度,并确切知道放大何时完成。 - 然后它将这些更新转发回渲染器用户界面(前端),使用
UPSCAYL_PROGRESS
和UPSCAYL_DONE
等命令。
结论
Electron主进程命令是将在渲染器用户界面(前端)中的交互与计算机的系统级操作连接起来的重要纽带。
它充当"控制中心",解释意愿,协调复杂的任务(如文件操作和运行外部程序),并将反馈传递给您。没有这个关键组件,Upscayl无法在桌面上执行任何核心功能
现在我们已经了解了谁下达命令,在下一章中,我们将深入探讨实际执行繁重工作的组件:放大二进制文件(upscayl-bin
),这是Upscayl魔力背后的力量