matlab - 如何在 MATLAB 中为并行外部进程创建异步等待栏?
问题描述
我需要等待一个过程以基本上未知的持续时间完成。我通过以下方式调用此过程:
output = system('foo.cmd')
进程foo
正在阻止任何进一步的代码执行。该过程通常需要大约 10 秒才能完成,并且不会返回任何状态,但之后会返回其输出值。有时需要一秒钟,有时需要一分钟或更长时间。为了模拟用户的进度,我想在执行之前实现一个等待栏,有点像:
function f = my_waitbar()
f = waitbar(0,'Please wait...');
for i=1:10
pause(1)
waitbar(i/10,f,'Executing foo');
end
waitbar(1,f,'Finishing, please wait...'); % should wait now and do nothing
end
然后foo.cmd
完成后我会关闭酒吧。
f = my_waitbar() % blocks my code from execution, therefore is pointless
output = system('foo.cmd')
close(f)
但是仅仅通过提前调用函数f = my_waitbar()
,该过程不会被并行触发。如何在my_waitbar()
不等待完成的情况下执行?
请注意,之后的一切system('foo.cmd')
都取决于它的执行,因此进一步的代码执行必须像现在一样等待它,所以system('foo.cmd &')
对我来说效果不佳。
编辑
请假设我对内容没有影响foo.cmd
解决方案
正如 Wolfie 已经提到的,标准进度条不适合等待具有未知持续时间(或未知迭代)的进程。在这些情况下,您最好使用微调器(gif 文件)、循环等待栏(文件交换中的好选择:cProgress)或无限进度条。这是我在这个例子中使用的:
现在如何使它成为可能。由于我无法复制您的确切过程 foo.cmd,因此我将其替换为 dos 命令dir
。因此,对于基线示例:
tic
command = 'dir' ;
[~,cmdout] = system(command) ;
toc
>> Elapsed time is 1.547987 seconds.
1.5 秒足以引起注意,并且cmdout
确实包含文件和目录的列表。所以我假设这与你的情况一样接近。
为了能够监控流程的结束,我将调用dir
(或在您的情况下调用foo.cmd
)打包到一个批处理文件中,该文件将:
- 检查文件 (
"MyProcessIsFinished"
) 是否存在。如果是,请删除它。 - 调用感兴趣的进程,将输出重定向到文件。
- 创建一个空文件
"MyProcessIsFinished"
这允许 MATLAB 调用批处理文件而无需等待结果(使用&
)。然后让 MATLAB 等到它检测到文件。检测到时,您知道该过程已完成,您可以关闭等待栏并继续执行代码。然后,您可以读取包含您用于获取的结果的文件cmdout
。
% initialise flag
processFinished = false ;
% start the continuous waitbar
hw = mywaitbar(0.5,'Please wait','Waiting for response ...',true);
% call the process in the batch file, without waiting for result
command = 'mycommand.bat &' ;
system(command) ;
% wait for the process to be finished
while ~processFinished
if exist('MyProcessIsFinished','file')
processFinished = true ;
end
end
close(hw) ; % close the wait bar
% now read your results
cmdout = fileread('outputfile.txt') ;
该文件mycommand.bat
现在是:
@echo off
if exist MyProcessIsFinished del MyProcessIsFinished
dir > outputfile.txt
copy nul MyProcessIsFinished > nul
exit
不要忘记dir > outputfile.txt
通过调用您的进程并重定向到合适的文件名来替换该行。它可能看起来像:
foo.cmd > ReceivedRequest.json
mywaitbar.m
连续的等待栏:我从文件交换中拿起: mywaitbar。代码很好,但我不得不改变一些东西来改进计时器管理,所以如果你想要一个工作版本,会有一些改变:
- 第 109 行:添加
'CloseRequestFcn',@closeRequestFcn
到新图形的属性。 - 第 120 行:添加
'Name','CircularWaitbarTimer'
到新计时器的属性中
然后在文件的底部,添加以下函数:
function closeRequestFcn(hobj,~)
% Delete the timer
t = timerfindall('Name','CircularWaitbarTimer') ;
if strcmpi('on',t.Running)
stop(t) ;
end
delete(t)
delete(hobj)
这将使等待栏实用程序更加稳定,并消除有关未正确管理的计时器的烦人警告/错误消息。
推荐阅读
- javascript - 不同文件中的Javascript变量冲突
- python - 为什么在我的代码中不需要将变量设置为空字符串?
- javascript - 我是否正确地将我的 Jquery 事件侦听器转换为 Javascript?我不明白 Javascript 是如何在不定位 id 的情况下工作的?
- java - 如何消除 Android Studio 中 NoActionBar 和 ImageView 之间的差距
- paypal - Paypal:xclick-auto-billing 是如何工作的?
- javascript - 不知道如何为我的随机报价生成器设置动画
- python - 如何获取“安全”字典的内容?
- flutter - 构建动态数据表
- python - 为什么字符串替换函数不尊重单词边界 \b 正则表达式?
- visual-studio-code - 用 JSON 编辑 VSCode 的设置?