鸿蒙开发异步并发:事件循环、Promise、TaskPool与Worker详解
我第一次在真机上把列表页滑到卡成PPT的时候说实话还挺意外的。代码看着一点毛病没有就是在一个点击回调里同步处理了一批图片的下载和解码结果整个页面僵住了一两秒。后来才反应过来鸿蒙开发的异步并发压根不是“进阶知识点”而是基本功——主线程承受不了任何超过十几毫秒的同步任务所有耗时操作都得想办法扔进异步链路。这篇就围绕鸿蒙开发的异步并发把事件循环、Promise/async/await、TaskPool、Worker这几层机制掰开揉碎讲透顺便附上我自己的选型和踩坑经验。适合刚接触ArkTS异步模型、或者已经写过但总在调度和性能上翻车的开发者。1. 先从线程模型说起为什么异步不等于开线程很多朋友一听说“异步并发”第一反应是“这不就是多线程吗”。这其实是最容易误导人的理解。ArkTS继承的模型和传统Java多线程不一样它更像JavaScript那套事件循环所有代码跑在一个主线程通过任务队列一个接一个地执行。1.1 事件循环单线程上的排队魔术ArkTS运行时把所有任务丢进一个队列主线程循环从队头取出任务执行执行完再取下一个。这个机制的好处是开发时不需要像C那样手动加锁坏处是只要队头某个任务执行太久后面所有任务都得等着。举一个实际现象你点击按钮触发一个方法这个方法的同步部分执行了500毫秒那在这500毫秒里页面点击、滚动、渲染全部没反应。等它跑完用户会感觉“卡住了一下”。这就是事件循环被阻塞了。异步的原理是把耗时的操作交接给系统底层去处理底层完成后把一个回调塞回主线程队列尾部主线程不会因为等你而卡住。这个过程叫“异步回调”是不开新线程也能实现的并发。1.2 掉帧、卡顿和页面无响应是从哪里来的鸿蒙UI渲染有自己的节奏通常每16毫秒左右刷新一帧。如果你在主线程同步做的任务超过这个时间就会掉帧掉帧超过几十毫秒用户能明显感受到滑动不跟手。我曾经在调试某个列表页时发现只要进入页面就开始同步遍历一个上万项的数组做数据处理帧率从60直接掉到20以下。把这段处理挪到异步机制里之后帧率立刻恢复了。要记住异步并发解决的不是“让代码执行更快”而是“避免主线程被拖死”让更重的活去后台跑跑完再汇报结果。1.3 异步与并发的边界Promise并不会创建新线程这儿最关键的一个认知是Promise本身不产生任何并行。new Promise只是把一个回调排到未来的事件循环位置它仍然跑在主线程上。真正的并行执行要么交给TaskPool系统管理的任务池要么交给Worker独立线程。所以实际项目里的套路是先用Promise/async/await处理“流程编排”把回调嵌套展开、把依赖关系写清楚再针对真正耗CPU或需要独立环境的任务丢到TaskPool或Worker里。二者结合才能叫异步并发。2. Promise与async/await异步编程的地基要打牢不管后面用TaskPool还是Worker绝大多数业务代码的异步骨架还是Promise那一套。这一层没打牢后面都是空中楼阁。2.1 一个Promise从创建到定案的过程Promise有四种状态pending进行中、fulfilled成功、rejected失败、settled已定案包含前两者。状态一旦变化就不可逆不能从成功再变回失败。写一个最简单的例子把回调式API包成Promisefunction downloadText(url: string): Promisestring { return new Promise((resolve, reject) { // 模拟某个耗时I/O setTimeout(() { if (url.length 0) { resolve(模拟下载内容); } else { reject(new Error(url为空)); } }, 1000); }); } downloadText(https://example.com/data) .then((content: string) { console.info(拿到数据 content); }) .catch((e: Error) { console.error(下载失败 e.message); });then里return的值会被包成新的Promise所以可以无限链下去。这个特性是后面做“串行依赖”的基础。2.2 async函数如何“伪装”成同步代码async函数永远返回一个Promise。它内部写起来像同步实际上遇到await会暂停等Promise定案后才继续执行。async function loadUserProfile(userId: string) { const authToken await requestToken(userId); const profile await requestProfile(authToken); return profile; }这两行await看起来像同步阻塞但它其实只等待当前Promise主线程在整个等待期间仍然可以处理其他渲染和事件——这就是async/await不卡UI的原因。有一点需要注意await一个普通值会直接把它当作已定案的结果立刻继续。如果你await了一个“看起来像Promise但实际根本不是Promise”的对象比如某个回调风格API的返回值那么代码不会等真正的异步操作完成直接往下走。这是很多隐性Bug的来源后面专门讲。2.3 错误处理的三个常见误区只catch async调用没catch链内Promiseasync函数内部有单独的Promise链时任何一环没有catch整个函数的reject可能冒泡到你意想不到的地方。try/catch只包await不包非异步逻辑同步阶段抛出的异常和await抛出的异常虽然都能捕获但排查时要分开看。把错误对象当普通值处理在ArkTS这种强类型环境里官方文档也强调尽量用Error对象的message而不是裸字符串。我现在项目里统一用async/await try/catch不用then链里的回调函数。可读性好而且断点调试起来方便多了。3. TaskPool短任务的并发执行池用对了才叫并行Promise解决了“把异步流程写得像同步”但真正需要多核并行、需要把任务扔出主线程的场合一般是TaskPool。它的定位是“让短小、独立的耗时任务在系统管理的线程池里跑”。3.1 最小可运行示例Concurrent与executeTaskPool的入口是ohos.taskpool模块。要提交的任务必须用Concurrent装饰器标记这意味着函数必须是一个独立的、不依赖外部上下文导出的纯函数。import { taskpool } from kit.ArkTS; Concurrent function computePrimes(count: number): number[] { const primes: number[] []; let num 2; while (primes.length count) { let isPrime true; for (let i 2; i * i num; i) { if (num % i 0) { isPrime false; break; } } if (isPrime) { primes.push(num); } num; } return primes; } async function runCompute() { const task new taskpool.Task(computePrimes, 10000); const result: number[] await taskpool.execute(task) as number[]; console.info(拿到 ${result.length} 个素数); }这里要点是execute返回一个Promise所以我在外层可以继续用await去等它。真实执行时TaskPool会把这个函数交给一个空闲的线程池线程跑跑完把结果带回主线程队列。传给TaskPool的参数必须是可序列化/可复制的运行时之间是隔离的你不能把一个对象引用直接丢进去共享。3.2 优先级和TaskGroup批量执行TaskPool支持三个优先级HIGH、MEDIUM、LOW。优先级影响的是在系统调度队列中的次序不是给任务分配更大的CPU别指望调HIGH就提速。批量执行场景用TaskGroup。它能把多个独立任务放进一个组统一execute再一次性收集结果import { taskpool } from kit.ArkTS; Concurrent function square(n: number): number { return n * n; } async function runGroup() { const group new taskpool.TaskGroup(); group.addTask(new taskpool.Task(square, 2)); group.addTask(new taskpool.Task(square, 4)); group.addTask(new taskpool.Task(square, 6)); await taskpool.execute(group); const results await group.collectResult(); console.info(JSON.stringify(results)); }我拿这个模式同时做过好几张图片的压缩每一个压缩任务都是纯函数加文件路径参数group统一调度最后collectResult拿到压缩后的路径数组再回到主线程刷新列表。整体耗时比串行压缩少了大概三分之二。3.3 取消与超时断了念想也要有手段TaskPool本身没有内置超时参数但任务对象可以被取消taskpool.cancel(task)。不过要注意cancel是“尽量取消”不是强制杀线程。如果任务已经跑起来了且没有响应取消标志它还是会跑完。想实现超时可以在外面手动包一层带超时逻辑的封装async function executeWithTimeoutT(task: taskpool.Task, timeoutMs: number): PromiseT { let timer: number -1; const timeoutPromise new PromiseT((_, reject) { timer setTimeout(() { reject(new Error(task timeout)); }, timeoutMs); }); const executePromise taskpool.execute(task) as PromiseT; return Promise.race([executePromise, timeoutPromise]).finally(() { clearTimeout(timer); }); }promise.race一旦超时分支胜出并不代表原任务停止它可能还在后台跑。所以超时逻辑要和cancel配合使用先cancel再抛超时错误至少保证UI层“看起来”已经把这件事作废了。4. Worker需要常驻线程时的第二种选择TaskPool不是万能的。当你有一个“长时间存活的线程任务”比如持续接收网络数据、做媒体流处理、跑一个循环引擎TaskPool会把一个池内线程长期占住影响其他任务的调度。这时候就该换Worker。4.1 Worker与TaskPool的本质差异TaskPool是由系统统一管理的线程池开发者不关心线程创建细节每个任务都是“即来即走”Worker则是你手动创建的一个独立线程生命周期由你控制。我用一个不太严谨但好记的类比TaskPool像外卖平台你把单子发出去由平台调度骑手完成任务每次骑手都不同Worker像你自己养了一个专职骑手虽然费用高但他只服务你这一个入口可以长期待命。选择依据很简单任务是一次性、独立、短时毫秒到秒级——选TaskPool。任务是常驻、需要持续运行、状态需要在线程内存里保留——选Worker。任务需要和UI生命周期绑定比如页面销毁时线程也要销毁——Worker更可控。4.2 创建一个Worker并让它跑起来创建Worker的大致步骤是新建一个Worker脚本文件里面用parentPort接收消息、处理、回传主线程用new Worker(...)拉起线程。主线程侧import { worker } from kit.ArkTS; const wk new worker.Worker(entry/ets/workers/MyWorker.ets); wk.onmessage (event: worker.MessageEvent) { console.info(收到Worker返回 JSON.stringify(event.data)); }; wk.onerror (err) { console.error(Worker异常 err.message); wk.terminate(); }; wk.postMessage({ cmd: start, payload: 100 });Worker脚本侧import { worker } from kit.ArkTS; const parentPort worker.parentPort; parentPort.onmessage (event: worker.MessageEvent) { const { cmd } event.data as { cmd: string }; if (cmd start) { // 长期跑一段耗时的模拟任务 let total 0; for (let i 0; i 10000000; i) { total i; } parentPort.postMessage({ cmd: done, total }); } };这里要留意Worker线程里不能直接访问UI组件所有和主线程的沟通都靠postMessage。你可以在Worker内维护自己的状态比如一个累计器、一个缓存Map这些状态在线程生命周期内自然保留不需要每次任务都重新初始化——这正是Worker比TaskPool更适合长驻任务的原因。4.3 通信开销与正确回收postMessage传数据本质是序列化/结构化克隆不是零拷贝共享引用。消息体越大序列化开销越明显。我测过传几MB的ArrayBuffer时通信耗时能从几毫秒涨到几十毫秒这个开销一旦在频繁交互场景下出现反而可能比直接在主线程算还慢。所以在Worker方案里需要处理好“传输频率”和“数据处理”的关系。大数据尽量分片处理或者只在关键节点同步结果别每算一步就postMessage一次。资源回收方面页面的aboutToDisappear或对应生命周期里最好调用wk.terminate()。Worker线程不会因为页面销毁而自动结束这是Worker和TaskPool在生命周期上的最大区别。不terminate的Worker会一直占着内存和CPU切片多个页面来回跳转甚至会积累出一堆僵尸线程。5. 异步流程编排把复杂业务拆成可靠链路把单个任务扔进TaskPool或Worker只是第一步真实业务里往往有依赖关系登录成功才能拉资料、拉完资料才能显示列表、多个独立请求要同时发出去并全部回来后才能渲染……这些“编排”操作决定了架构是清爽还是乱成一团。5.1 串行依赖与Promise链串行依赖最直观的写法是回调嵌套但嵌套深了就成了“回调地狱”。我习惯用Promise链或async/await把每一步解耦async function openUserCenter(userId: string) { const token await login(userId); const profile await fetchProfile(token); const badges await fetchBadges(profile.userId); renderUserCenter(profile, badges); }每一步之间是清晰的线性关系改任何一步只需要动对应函数。如果想在中间插入一步缓存比如先从本地缓存读读不到再请求直接加一个逻辑分支就行不会破坏整体结构。5.2 并行聚合Promise.all与TaskGroup的取舍很多人遇到“同时做两件事”就顺手写两个await比如const a await fetchDataA(); const b await fetchDataB();这样其实是串行的B要等A完成才开始。如果A和B之间没有依赖这里明显浪费了一倍时间。应该改成const [a, b] await Promise.all([fetchDataA(), fetchDataB()]);在Promise.all里两个请求是同时发出的总耗时约等于最慢的那个。但如果“同时做两件事”指的是两个CPU密集计算比如图片压缩——这里再用Promise.all就不对了因为Promise.all并不会提升计算并行度它只是同时发起请求CPU计算终究还挤在主线程。这种场景应该交给TaskGroup让任务池里的线程真并行跑。所以我的日常原则是I/O类并行用Promise.allCPU类并行用TaskGroup。两者看着像“并行聚合”底层完全不同。5.3 失败补偿与部分结果的处理Promise.all有一个fail-fast语义任何一个请求失败整体立刻reject其他结果全部丢弃。这在某些场景过于激进你同时拉三个榜单数据一个失败两个成功你希望显示已成功的那两个而不是整个页面白屏。处理方式有两种。一种是给每个子请求单独加catch保证每个分支都settleconst safeFetchA fetchDataA().catch(() null); const safeFetchB fetchDataB().catch(() null); const [a, b] await Promise.all([safeFetchA, safeFetchB]);另一种是用TaskGroup的collectResult它会把每个任务的结果汇总你可以自己过滤失败项。至于最终是全量成功再更新还是部分成功也更新取决于业务容忍度。我的建议是页面主数据用Promise.all保证一致性次要数据用单独分支catch失败时显示占位。6. 我在异步并发上踩过的几个坑这一节是真正的经验之谈。以下问题我都亲身调试过每一个都花了不止一个晚上才定位根因分享出来希望大家绕着走。6.1 坑一TaskPool函数“偷偷”引用外部变量TaskPool要求Concurrent函数不能捕获外部闭包变量、不能依赖外部全局状态。问题是编译阶段有时能拦住有时候你用了各种间接引用绕过了检查结果运行时就会出怪事。我遇到过一次某计算任务需要读取一个配置对象我在Concurrent函数内部竟然通过一个全局变量去取配置编译没报错运行结果却是随机错误——有时算对有时算错。后来才意识到那个配置对象的拷贝在线程间并不同步数据已经被改乱了。排查这类问题先看并发任务的入参是否是纯数据再看函数体是否能脱离宿主环境独立运行。最稳的做法是把所有需要的数据全部作为参数传进去一个都不要从外部拿。6.2 坑二长任务塞进任务池把调度器拖垮有一段时间某功能扫描本地文件夹生成缩略图我图省事直接把它们都提交成了TaskPool任务。单个任务本身不慢但数量多、总时长达几分钟结果后续提交的其他简单任务全部排队等待响应性能肉眼可见地变差。原因很简单TaskPool线程数是有限的。每条线程一旦被长任务占住短任务就只能在队列里等。后来我做了拆分超过5分钟级的后台扫描改造成Worker常驻线程TaskPool只处理单个计算密集的小任务。问题立刻消失。我现在的经验是TaskPool适合“毫秒到秒级”的任务。任务一旦有“长时间、持续、状态化”的特征尽早切换到Worker。6.3 坑三await了一个回调式API被静默穿透之前接入过一个老模块它提供了回调风格的读取接口但返回值不是Promise而是直接返回一个对象或undefined。我在调用时习惯写了await结果await直接穿透了后续代码立刻执行还没读到的数据被当成空值用页面先是空白然后异步数据回来了又触发一次刷新又闪一下。排查过程中我打了几个断点发现代码执行顺序完全不对await下一行竟然比回调更早执行。这才意识到问题出在“await对象的成色”。规范做法是把这类回调式API先Promise化明确告诉运行时“你要等这个结果”function readConfig(cb: (cfg: Config) void): void { // 老模块的回调式接口 } function readConfigAsync(): PromiseConfig { return new Promise((resolve) { readConfig((cfg) resolve(cfg)); }); }所有对外暴露的异步入口都统一成Promise风格不让原始回调API直接在业务代码里被await。6.4 坑四一await到底把并行写成了串行这个坑和第5章说的Promise.all是同一个问题但想强调一个反直觉点加await不等于更稳反而可能更慢。我有一次重构列表加载把拉首页推荐位、拉用户偏好、拉配置三个请求顺序写了三个await。逻辑很清晰结果首屏加载时间从和原来“三个并行回调”一样变成了三倍用户反馈页面启动明显慢了。后来改成Promise.all恢复到了原来的水平。这里给大家一个判断标准两个异步操作之间如果没有“上一步的结果作为下一步入参”的关系就不应该用await把它们串起来而应该先同时发起最后统一await。7. 选型与模板给日常开发一个不纠结的清单看完前面这么多机制真到写代码时可能还是纠结这个任务该丢TaskPool还是Worker该用Promise.all还是TaskGroup我整理了一个决策表和一套可以直接套用的代码骨架。7.1 一张先看选型的决策表场景推荐机制理由单次网络I/O后再更新UIasync/await PromiseI/O并发由系统底层完成Promise编排足够同时发起多个独立I/O请求Promise.all多个请求同时发送等待整体回包图片压缩、加密、复杂计算单次TaskPool短任务、无状态、系统调度线程池批量CPU计算多个独立计算结果TaskGroup真并行批量收集结果需要长时间运行的流式处理Worker常驻线程状态可保留在线程内任务要与页面生命周期绑定Worker可手动terminate避免被系统池策略误伤任务运行后可取消TaskPool cancel 竞速超时TaskPool的cancel粒度足够业务侧使用这张表不是绝对的但90%的场景照着选不会错。7.2 可以直接抄的异步链路代码骨架最后给一个我在实际业务中反复使用的骨架把所有机制串起来事件触发 → 主线程用async/await编排 → CPU密集部分丢TaskPool → 结果回到主线程刷新UI。import { taskpool } from kit.ArkTS; Concurrent function heavyProcess(input: string): string { // 模拟长时间处理 let result ; for (let i 0; i 1000000; i) { result input i % 7; } return result; } async function onSomeButtonClick(input: string) { try { const task new taskpool.Task(heavyProcess, input); const output await taskpool.execute(task) as string; // 回到主线程更新UI this.model.setOutput(output); } catch (error) { // 统一错误处理避免未捕获异常 console.error(处理失败: ${(error as Error).message}); } }有了这个骨架再往里面加多层依赖、多个并行请求、一个常驻Worker只需要往相应位置填充业务逻辑就够了。我在实际项目里还有一个不成文的习惯所有异步入口都尽量返回Promise所有耗时任务先判断“是一次性还是常驻”再决定用TaskPool还是Worker所有并行聚合先看是I/O等待还是CPU计算。这套思维养成了异步并发的坑至少能避开九成。

相关新闻

手写 Tool Use 三种方案:从正则到 ReAct 循环,面试与实战全拆解

手写 Tool Use 三种方案:从正则到 ReAct 循环,面试与实战全拆解

面试复盘,总得写点能救命的干货。前段时间面某大模型应用岗,聊到 Agent 相关的项目经历,面试官突然来了句:“那你现在手写一个 Tool Use,不用跑通,给我看看思路。” 当时白板上一片空白,我脑子里过了三个版…

2026/10/16 13:16:18 阅读更多 →
ResNet迁移学习推理实战:predict.py权重加载与预处理全解析

ResNet迁移学习推理实战:predict.py权重加载与预处理全解析

1. 项目概述与核心需求拆解1.1 为什么单独给“预测”写一篇很多做迁移学习的同学,训练完模型就以为万事大吉,等真正要拿模型去用的时候,才发现还有一堆细节没处理。比如:训练时数据是归一化过的,预测时忘了对输入做同样…

2026/10/16 13:16:18 阅读更多 →
Kubernetes内部域名自动解析:Ingress与ExternalDNS实战指南

Kubernetes内部域名自动解析:Ingress与ExternalDNS实战指南

给内部系统配域名这事,我折腾了不少时间。事情的起因其实很普通:托管 Kubernetes 集群里服务越来越多,IP 不断在变,DNS 记录却一直靠手动加。做过一次以后我就确信,必须有个东西能让域名跟着 Kubernetes 资源自动变。最…

2026/10/16 13:16:18 阅读更多 →

最新新闻

C#.NET整合微信支付宝银联支付:回调验签与统一网关实践

C#.NET整合微信支付宝银联支付:回调验签与统一网关实践

简介:面向C# .NET开发人员的多支付渠道整合方案,聚焦微信、支付宝与银联支付在统一业务后台中的接入与协同。内容覆盖微信JSAPI、Native、H5、APP,支付宝网页支付、APP支付、扫码支付,以及银联网上支付、快捷支付等典型场景&#…

2026/10/16 13:51:34 阅读更多 →
OpenCV 4.5.1环境搭建:源码编译contrib与VS2019配置完整指南

OpenCV 4.5.1环境搭建:源码编译contrib与VS2019配置完整指南

简介:面向使用 VS2019 搭建 OpenCV 4.5.1 扩展开发环境的学习者,尤其是被 CMake 配置、opencv_contrib 模块缺失反复卡住的新手。作者将耗时五天的踩坑过程整理为可直接复用的现成环境包:下载 zip 并解压后,按配套博文步骤配置&am…

2026/10/16 13:51:34 阅读更多 →
GPOPS2高精度最优控制求解原理与MATLAB实战

GPOPS2高精度最优控制求解原理与MATLAB实战

简介:本资源是面向控制工程、航空航天及优化算法研究者的GPOPS2数值优化工具包,专为解决多阶段动态优化问题设计,尤其适用于飞行器轨迹规划、机器人路径设计与航天器轨道优化等高精度建模场景,需具备MATLAB编程基础与非线性优化理…

2026/10/16 13:51:34 阅读更多 →
2026年国内AI大模型API聚合平台排名前十推荐:实测选型与避坑指南

2026年国内AI大模型API聚合平台排名前十推荐:实测选型与避坑指南

两个前提,先立规矩 这类榜单文章满天飞,先把话说明白:其一,拒绝营销套路,额度虚标、服务停摆风险、变相收费一律过滤;其二,拒绝参数堆砌,只看三样东西——真实到账价格、实际响应速度…

2026/10/16 13:51:34 阅读更多 →
从RISC-V到全国产载板:嵌入式核心板推荐中值得关注的众达科技进迭时空K3方案

从RISC-V到全国产载板:嵌入式核心板推荐中值得关注的众达科技进迭时空K3方案

国产嵌入式算力重构背景下的核心板选型困惑2026年,工业控制、边缘计算、装备信息化以及具身智能等设备端场景,正在把「嵌入式核心板」从传统配套器件推到系统架构的中心位置。过去很长一段时间里,核心板选型往往沿用x86或进口ARM生态的成熟方…

2026/10/16 13:51:34 阅读更多 →
上位机软件架构设计:分层思路与通信层实践

上位机软件架构设计:分层思路与通信层实践

上位机软件架构设计,说穿了就是解决一件事:让一台天天连设备、发指令、收数据的电脑程序,能经得起需求变化和长期维护。我做了几年的设备上位机开发,从最开始“界面上一堆按钮,背后全塞在一起”的小工具,到…

2026/10/16 13:50:33 阅读更多 →

日新闻

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

个人 AI Agent 平台接入 TaoToken:统一 Key 与 API 通道的配置大纲

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 0:00:05 阅读更多 →
信号与系统频域分析作业解题指南

信号与系统频域分析作业解题指南

1. 作业背景与核心要求解析信号与系统作为电子信息类专业的核心基础课,其作业设计往往直接关联课程的核心知识框架。2026年春季第六次作业的布置,通常对应着课程进展到频域分析的关键阶段。根据常规教学进度推测,本次作业可能涉及以下核心内容…

2026/10/16 0:00:05 阅读更多 →
Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

Django MVT实战:从零构建图书借阅系统,彻底搞懂Model-View-Template分层

1. 从一个"四不像"的练手项目说起如果你已经看完了Django的官方教程前几章,跟着敲完了投票应用,大概会有一种"我好像会了,又好像什么都不会"的割裂感。教程里每个知识点都是拆开的——这一章讲模型,下一章讲视…

2026/10/16 0:00:05 阅读更多 →

周新闻

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

流感时间序列预测实战:ARIMA/LSTM全流程拆解与避坑指南

简介:基于 ARIMA、LSTM、Transformer 等模型的流感时间序列预测 Python 源码,面向计算机相关专业课程设计与期末大作业学生,以及项目实战学习者。内容覆盖预处理、平稳性检验、定阶、残差分析、多模型对比预测的完整时序建模流程,…

2026/10/15 16:18:54 阅读更多 →
影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别

影刀RPA新手教程:键盘模拟输入实战——输入文本与模拟按键的区别 做影刀RPA自动化,十个新手有八个栽在"往输入框里填东西"这件事上:要么填不进去,要么填了一半,要么直接把原来内容追加在后面。这背后的根因&…

2026/10/15 19:41:51 阅读更多 →
影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容

影刀RPA新手教程:阅文起点小说数据采集实战——书籍信息与章节内容 1. 认识影刀:什么场景该用RPA采小说数据 起点中文网的页面结构相对稳定——分类榜单、书籍详情、章节内容三块独立页面,跳转链路清晰。这种场景非常适合影刀自动化&#x…

2026/10/15 13:48:15 阅读更多 →

月新闻

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

我发现了一个新思路:用 Remotion + Claude Code 像写代码一样自动化生成短视频

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 0:14:36 阅读更多 →
Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

Windows下 Codex 中 Chrome 和 Computer Use 插件不可用问题排查及解决参考方式:TaoToken 统一 Key 配置与验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/16 3:49:43 阅读更多 →
黑夜航拍船只数据集训练YOLOV5模型全流程解析

黑夜航拍船只数据集训练YOLOV5模型全流程解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

2026/10/15 9:49:14 阅读更多 →