OpenClaw CLI 命令参考手册

核心内容摘要

30美元打造颠覆式AI智能眼镜:零门槛DIY全攻略
OFA VQA模型开源镜像:基于ModelScope iic/ofa_visual-question-answering_pretrain_large_en

Pytorch与CUDA版本对照表:如何为你的显卡选择最佳组合(2023最新)

æ–‡ç« ç›®å½•å‰�言一ã€� ç�†è§£ Actor 模å�‹è¿™ä¸€åº§åº§å­¤å²›äºŒã€� TaskPooléš�å�«éš�到的特ç§�部队三ã€� Worker常驻å��å�°çš„专è�Œç®¡å®¶å››ã€� 通信机制ä»�“拷è´�â€�到“转移â€�五ã€�å®�战示例六ã€� 总结ä¸�å®�战å‰�言在移动应用开å�‘中æµ�畅度就是生命线。用户的手指在å±�幕上滑动的æ¯�一毫秒系统都需è¦�在 16ms 内完æˆ�一帧画é�¢çš„æ¸²æŸ“。如æ�œæˆ‘们的主线程也就是 UI 线程被任何耗时的æ“�ä½œå µå¡�哪怕å�ªæ˜¯è¯»å�–一个ç¨�大的文件或者进行一次å¤�æ�‚的数学è¿�算界é�¢å°±ä¼šç«‹åˆ»æ�‰å¸§ç”šè‡³å®Œå…¨å�¡æ­»ã€‚è¿™ç§�体验对äº�用户æ�¥è¯´æ˜¯ç�¾é𾿀§çš„。在 Java 或 C çš„ä¼ ç»Ÿå¼€å�‘ä¸­æˆ‘ä»¬ä¹ æƒ¯äº†ç›´æ�¥new Threadæˆ–è€…ä½¿ç”¨çº¿ç¨‹æ± æ�¥åˆ†æ‹…任务但在鸿蒙 HarmonyOS 6 (API

çš„ ArkTS 引æ“�中并å�‘模å�‹å�‘ç”Ÿäº†ä¸€äº›æ ¹æœ¬æ€§çš„å�˜åŒ–。ArkTS 采用了Actor å¹¶å�‘模å�‹è¿™æ„�味ç�€çº¿ç¨‹ä¹‹é—´æ²¡æœ‰å…±äº«å†…存也没有那令人头秃的é”�机制。今天我们就æ�¥è�Šè�Šå¦‚何在这个新模å�‹ä¸‹åˆ©ç”¨TaskPoolå’ŒWorker优雅地处ç�†è€—时任务把主线程的å®�贵资æº�还给 UI 渲染。一ã€� ç�†è§£ Actor 模å�‹è¿™ä¸€åº§åº§å­¤å²›è¦�æ�Œæ�¡é¸¿è’™çš„å¹¶å�‘首先得扭转一个观念线程之间ä¸�å†�能éš�æ„�访问å�Œä¸€ä¸ªå�˜é‡�äº†ã€‚åœ¨ä¼ ç»Ÿçš„å…±äº«å†…å­˜æ¨¡å�‹ä¸­å¤šä¸ªçº¿ç¨‹å�¯ä»¥å�Œæ—¶è¯»å†™å�Œä¸€ä¸ªå…¨å±€å�˜é‡�为了防止数æ�®é”™ä¹±æˆ‘们ä¸�å¾—ä¸�引入å�„ç§�é”�Lockå’Œå�Œæ­¥æœºåˆ¶è¿™å¾€å¾€æ˜¯æ­»é”�å’Œç«�æ€�æ�¡ä»¶çš„æ¸©åºŠã€‚而 ArkTS 采用的 Actor 模å�‹å°†æ¯�ä¸€ä¸ªçº¿ç¨‹æ— è®ºæ˜¯ä¸»çº¿ç¨‹ã€�TaskPool 线程还是 Worker 线程都视为一个独立的 Actorã€‚ä½ å�¯ä»¥æŠŠå®ƒä»¬æƒ³è±¡æˆ�一个个独立的“房间â€�æ¯�个房间里有自己的内存空间。A 房间的人想è¦�把数æ�®ç»™ B 房间ä¸�能直æ�¥æŠŠæ‰‹ä¼¸è¿‡å�»è€Œå¿…须通过“å�‘消æ�¯â€�的方å¼�把数æ�®å¤�åˆ¶ä¸€ä»½ä¼ é€’è¿‡å�»ã€‚è¿™ç§�è®¾è®¡çš„æœ€å¤§å¥½å¤„å°±æ˜¯å¤©ç„¶æ— é”�彻底æ�œç»�了数æ�®ç«�争带æ�¥çš„ Bugæ��大地æ��高了系统的稳定性。但代价就是我们在设计代ç �时必须时刻关注数æ�®çš„ä¼ é€’æˆ�本。二ã€� TaskPooléš�å�«éš�到的特ç§�部队在 API 20 中鸿蒙官方强烈æ�¨è��首选TaskPoolä»»åŠ¡æ± æ�¥å¤„ç�†å¹¶å�‘ä»»åŠ¡ã€‚ä½ å�¯ä»¥æŠŠå®ƒçœ‹ä½œæ˜¯ä¸€ä¸ªæ™ºèƒ½çš„网约车调度平å�°ã€‚å½“ä½ æœ‰ä¸€ä¸ªè€—æ—¶ä»»åŠ¡æ¯”å¦‚å›¾ç‰‡æ»¤é•œå¤„ç�†æ—¶ä½ ä¸�需è¦�自己å�»åˆ›å»ºçº¿ç¨‹ä¹Ÿä¸�需è¦�关心线程的生命周期å�ªéœ€è¦�把任务包装好扔给 TaskPoolã€‚ç³»ç»Ÿä¼šè‡ªåŠ¨æ ¹æ�®å½“å‰�的负载情况ã€�任务优先级安æ�’一个空闲的线程æ�¥æ‰§è¡Œå®ƒã€‚使用 TaskPool çš„æ ¸å¿ƒåœ¨äº�Concurrent装饰器。我们需è¦�将耗时的逻辑å°�装æˆ�ä¸€ä¸ªç‹¬ç«‹çš„å‡½æ•°å¹¶æ‰“ä¸Šè¿™ä¸ªæ ‡è®°ã€‚è¿™ä¸ªå‡½æ•°å¿…é¡»æ˜¯çº¯å‡½æ•°æˆ–è€…é�™æ€�方法ä¸�能ä¾�赖外部的 UI 组件状æ€�å› ä¸ºå®ƒæ˜¯è¦�被å�‘é€�到å�¦ä¸€ä¸ªçº¿ç¨‹å�»æ‰§è¡Œçš„。当我们调用taskpool.execute时系统会将函数的å�‚æ•°åº�列化å��æ‹·è´�到工作线程执行完毕å��å†�将结æ�œåº�列化拷è´�å›�主线程。这ç§�机制é��常适å�ˆé‚£äº›ç‹¬ç«‹ã€�短时ã€�高 CPU 消耗的任务比如大图å�‹ç¼©ã€�å¤�æ�‚算法计算等。TaskPool 会自动进行负载å�‡è¡¡å½“任务过多时会自动扩容空闲时会自动缩容完全ä¸�需è¦�å¼€å�‘者æ“�心。三ã€� Worker常驻å��å�°çš„专è�Œç®¡å®¶æ—¢ç„¶æœ‰äº† TaskPool为什么还需è¦�WorkerTaskPool 虽好但它本质上是任务导å�‘的执行完就释放。如æ�œä½ 的应用需è¦�一个长时间è¿�行的å��å�°çº¿ç¨‹æ¯”如需è¦�一直ä¿�æŒ�一个 WebSocket é•¿è¿�æ�¥æˆ–者需è¦�一个常驻的数æ�®åº“读写å�¥æŸ„那么 TaskPool å°±ä¸�太å�ˆé€‚了。Worker æ›´åƒ�æ˜¯ä¸€ä¸ªä½ ä¸“é—¨é›‡ä½£çš„â€œå…¨è�Œå‘˜å·¥â€�ã€‚ä½ éœ€è¦�手动创建它new worker.ThreadWorker它拥有独立的文件上下文worker.tså¹¶ä¸”ä¼šä¸€ç›´å­˜æ´»ç›´åˆ°ä½ æ˜¾å¼�地调用terminate销æ¯�它。Worker 适å�ˆå¤„ç�†é‚£äº›ç”Ÿå‘½å‘¨æœŸè¾ƒé•¿ã€�状æ€�需è¦�ä¿�æŒ�的场景。在 Worker 线程中我们通过postMessageå�‘主线程å�‘é€�消æ�¯ä¸»çº¿ç¨‹é€šè¿‡onmessageæ�¥æ”¶ã€‚虽然æµ�程比 TaskPool ç¹�ç��一些但它æ��供了更精细的线程æ�§åˆ¶èƒ½åŠ›ã€‚éœ€è¦�注æ„�的是Worker 的数é‡�是有é™�制的通常最多 8 个且创建和销æ¯�都有一定的资æº�开销所以å�ƒä¸‡ä¸�è¦�滥用。四ã€� 通信机制ä»�“拷è´�â€�到“转移â€�å‰�é�¢æ��到Actor 模å�‹çš„æ•°æ�®é€šä¿¡ä¾�èµ–äº�åº�列化和å��åº�列化也就是拷è´�Structured Clone。对äº�普通的 JSON 对象或å°�æ•°æ�®è¿™ç§�å¼€é”€å‡ ä¹�å�¯ä»¥å¿½ç•¥ä¸�计。但如æ�œä½ è¦�ä¼ é€’ä¸€å¼ 10MB çš„ä½�图数æ�®æˆ–者一个巨大的 Float32Arrayæ‹·è´�带æ�¥çš„ CPU 和内存消耗就是巨大的甚至å�¯èƒ½æŠµæ¶ˆå¤šçº¿ç¨‹å¸¦æ�¥çš„æ€§èƒ½çº¢åˆ©ã€‚为了解决这个问题鸿蒙引入了Transferable Object转移对象的概念。对äº� ArrayBuffer 这类二进制数æ�®æˆ‘们å�¯ä»¥é€‰æ‹©â€œè½¬ç§»â€�æ�§åˆ¶æ�ƒè€Œä¸�是拷è´�。就åƒ�我把手里的公文包直æ�¥é€’ç»™ä½ æˆ‘è¿™é‡Œæ²¡æœ‰äº†ä½ é‚£é‡Œæœ‰äº†ä¸­é—´ä¸�需è¦�å¤�å�°æ–‡ä»¶ã€‚在代ç �中我们在postMessage或者 TaskPool çš„å�‚数中å�¯ä»¥å°†è¿™äº›å¯¹è±¡æ ‡è®°ä¸º Transferable。一旦转移å�Ÿçº¿ç¨‹å°±æ— 法å†�访问这å�—内存了访问会报错ä»�而å®�ç�°äº†é›¶æ‹·è´�Zero Copyçš„æ��速通信。这是在处ç�†éŸ³è§†é¢‘æµ�ã€�图åƒ�处ç�†ç­‰å¤§æ•°æ�®åœºæ™¯ä¸‹çš„å¿…æ�€æŠ€ã€‚五ã€�å®�战示例下é�¢æ‹Ÿäº†ä¸€ä¸ªâ€œå›¾ç‰‡é«˜æ–¯æ¨¡ç³Šå¤„ç�†â€�的耗时场景。我们在主界é�¢ä¸Šæ”¾äº†ä¸€ä¸ªåŠ è½½åœˆé€šè¿‡ TaskPool 在å��å�°çº¿ç¨‹è¿›è¡Œæ•°äº¿æ¬¡çš„æ•°å­¦è¿�ç®—ä½ ä¼šå�‘ç�°ä¸»ç•Œé�¢çš„åŠ è½½åœˆä¾�然转得ä¸�滑æµ�畅完全没有被å�¡é¡¿ã€‚import { taskpool } from kit.ArkTS; import { promptAction } from kit.ArkUI; // ------------------------------------------------------------- //

定义并å�‘任务函数 // ------------------------------------------------------------- // 必须使用 Concurrent 装饰器 // 这个函数将在独立的线程中è¿�行ä¸�能访问外部的 this 或 UI 状æ€� Concurrent function heavyImageProcess(buffer: ArrayBuffer, iterations: number): ArrayBuffer { // 模拟耗时æ“�作例如对图片åƒ�ç´ è¿›è¡Œå¤�æ�‚的矩阵è¿�ç®— const startTime Date.now(); console.info([TaskPool] 任务开始执行); // 这里我们用空循ç�¯æ¨¡æ‹Ÿ CPU 密集å�‹è®¡ç®— // å®�际场景中这里是对 buffer 进行åƒ�ç´ çº§æ“�作 let result 0; for (let i 0; i iterations; i) { result Math.sqrt(i) * Math.sin(i); } const endTime Date.now(); console.info([TaskPool] 任务完æˆ�耗时: ${endTime - startTime}msè®¡ç®—æ ¡éªŒå€¼: ${result.toFixed(

}); // 返�处��的数� (此处直�返��数�用�演示) // 注�默认情况下返�值会通过�列化拷��主线程 // 如�使用 setTransferList则�需�拷� return buffer; } Entry Component struct ThreadConcurrencyPage { State isProcessing: boolean false; State processResult: string 等待处�...; State progressValue: number 0; // 用�模拟 UI 动画的定时器验�主线程是��死 private animationTimer: number -1; aboutToAppear(): void { // �动一个主线程动画�� UI 没�死 // � 50ms 更新一次进度让进度�转动 this.animationTimer setInterval(() { this.progressValue (this.progressValue

% 100; },

; } aboutToDisappear(): void { clearInterval(this.animationTimer); } // ------------------------------------------------------------- //

触� TaskPool 任务 // ------------------------------------------------------------- async startAsyncTask() { if (this.isProcessing) return; this.isProcessing true; this.processResult 正在��线程全速计算中...; try { // 模拟一个 10MB 的图片数� const imageSize 1024 * 1024 * 10; const mockBuffer new ArrayBuffer(imageSize); // 创建 Task 对象 // �数1: Concurrent 函数 // �数

..n: ä¼ é€’ç»™å‡½æ•°çš„å�‚æ•° const task new taskpool.Task(heavyImageProcess, mockBuffer,

; // ã€�性能优化关键点】 // 如æ�œæ•°æ�®å¾ˆå¤§å¼ºçƒˆå»ºè®®ä½¿ç”¨ setTransferList å°† ArrayBuffer çš„æ�§åˆ¶æ�ƒâ€œè½¬ç§»â€�ç»™å­�线程 // è¿™æ ·ä¸»çº¿ç¨‹çš„ mockBuffer å°†ç�¬é—´å�˜å¾—ä¸�å�¯ç”¨ (byteLength 为

但é�¿å…�了巨大的拷è´�开销 // 如æ�œå¼€å�¯ä¸‹é�¢è¿™è¡Œæ³¨é‡Šä¼ å…¥å­�线程是零拷è´�但主线程这边的 mockBuffer 就废了 // task.setTransferList([mockBuffer]); // 执行任务并等待结æ�œ // execute è¿”å›�的是 Promiseä¸�会阻å¡�当å‰�主线程 const result await taskpool.execute(task); // ç±»å�‹æ–­è¨€ç¡®ä¿�è¿”å›�的是 ArrayBuffer const resultBuffer result as ArrayBuffer; this.processResult 处ç�†æˆ�功\næ•°æ�®å¤§å°�: ${(resultBuffer.byteLength / 1024 /

.toFixed(

} MB; promptAction.showToast({ message: ��任务执行完毕 }); } catch (e) { console.error(Task execution failed: ${JSON.stringify(e)}); this.processResult 处�失败; } finally { this.isProcessing false; } } build() { Column() { Text(TaskPool 多线程并�) .fontSize(

.fontWeight(FontWeight.Bold) .margin({ top: 40, bottom: 20 }) // 状�展示区 Column({ space: 20 }) { // 一个一直在动的进度�用�检测 UI 线程是��顿 // 如�主线程被阻�这个进度�会�止转动 Progress({ value: this.progressValue, total: 100, type: ProgressType.Ring }) .width(

.height(

.color(#0A59F

.style({ strokeWidth: 10 }) .animation({ duration: 100 }) Text(this.processResult) .fontSize(

.fontColor(#

.textAlign(TextAlign.Center) .padding(

} .width(90%) .padding(

.backgroundColor(Color.White) .borderRadius(

.shadow({ radius: 10, color: #1A000000 }) .margin({ bottom: 40 }) // �作按钮 Button(this.isProcessing ? 正在计算中... : 开始耗时计算 (5000万次)) .width(80%) .height(

.backgroundColor(this.isProcessing ? #CCCCCC : #0A59F

.enabled(!this.isProcessing) .onClick(() { this.startAsyncTask(); }) Text(��说�\n点击按钮�TaskPool 会在��线程执行数�万次浮点�算。请观察上方的进度圈它�然���畅转动说�主线程UI线程未被阻�。) .fontSize(

.fontColor(#

.padding(

.lineHeight(

} .width(100%) .height(100%) .backgroundColor(#F1F3F

} }六� 总结��战在鸿蒙 HarmonyOS 6 的开�中“主线程�� UI 渲染和轻�逻辑耗时任务一律扔给���应当�为我们的肌肉记忆。对��大多数场景TaskPool是最简�高效的选择它�蔽了线程管�的��性而对�需�长时�活的逻辑Worker则是��或缺的补充。�时我们�善用ArrayBuffer和转移机制�优化大数�通信的性能。

78直接c13-78直接应用

百度百家号客服电话人工服务

123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123 123