是的,我认为您必须更改代码以使用 async 模式,因为否则,您将阻塞要同时渲染进度对话框的UI线程。
这是使用spawn
和spawnSync
之间的区别:
如何在 async 方法中从子进程输出中读取示例:
let childProcess = spawn(someProcessToSpawn)
.on("close",(code,signal) => {
console.log(`Closed: ${code} ${signal}`);
if (childProcess.killed) { console.log('KILLED'); }
resolve();
clearInterval(interval);
})
.on("error",err => {
reject(err);
});
childProcess.stdout
.on("data",(chunk: string | Buffer) => {
// YOUR CODE GOES HERE
console.log(`stdout: ${chunk}`);
progressUpdate = chunk.toString('utf8',50).replace(/[\r\n]/g,'');
});
如果要运行整个示例,请克隆progress-sample,运行npm install
并用以下代码替换 extension.ts 内容:
'use strict';
import { ExtensionContext,window,commands,ProgressLocation,CancellationToken,Progress } from 'vscode';
import { spawn,spawnSync } from 'child_process';
export function activate(context: ExtensionContext) {
context.subscriptions.push(commands.registerCommand('extension.startTask',async () => {
let mode = await window.showQuickPick(['sync','async'],{ placeHolder: 'Pick mode...' });
window.withProgress({
location: ProgressLocation.Notification,title: "I am long running",cancellable: true
},async (progress,token) => {
token.onCancellationRequested(() => {
console.log("User canceled the long running operation");
});
switch (mode) {
case undefined:
return; // canceled by the user
case 'sync':
return spawnSomethingSync(token);
case 'async':
default:
return spawnSomethingAsync(progress,token);
}
});
}));
}
/**
* Synchronous approach
* @param _token cancellation token (unused in the sync approach)
*/
function spawnSomethingSync(_token: CancellationToken): Promise<void> {
return new Promise(resolve => {
console.log('Started...');
let child = spawnSync('cmd',['/c','dir','/S'],{ cwd: 'c:\\',encoding: 'utf8' });
console.log(`stdout: ${child.stdout.slice(0,1000)}`); // otherwise it is too big for the console
resolve();
});
}
/**
* Asynchronous approach
* @param token cancellation token (triggered by the cancel button on the UI)
*/
function spawnSomethingAsync(progress: Progress<{ message?: string; increment?: number }>,token: CancellationToken): Promise<void> {
return new Promise<void>((resolve,reject) => {
if (token.isCancellationRequested) {
return;
}
var progressUpdate = 'Starting up...';
const interval = setInterval(() => progress.report({ message: progressUpdate }),500);
let childProcess = spawn('cmd',{ cwd: 'c:\\' })
.on("close",'');
});
token.onCancellationRequested(_ => childProcess.kill());
});
}
如果您不在Windows上,只需用其他适当的长期运行命令替换dir /S
和c:\\
。
使用 async 方法的另一个好处是,可以很容易地将“取消”按钮连接起来以杀死生成的进程:
token.onCancellationRequested(_ => childProcess.kill());
...,您还可以通过更新progress
对象来显示进度。
本文链接:https://www.f2er.com/3139204.html