我正在撰寫一個函式,它會做一些作業來向呼叫者提供結果;但是一旦完成這項作業,就會存在一些呼叫者不需要但知道將來會有用的后續作業。我希望在 MATLAB 行程不再忙于執行它立即需要的操作時執行此后續作業,這樣它就不會減慢速度,或者更糟地阻止其他優先任務的執行。
在前端界面上,MATLAB 對代碼當前是否正在執行有清晰的感知。如果有,狀態欄會顯示“忙碌”,并且編輯器功能區條會更新以顯示“暫停”按鈕以中斷執行。您可以在命令視窗中輸入新命令,但在當前執行的代碼完成之前,它們不會被讀取和執行。執行完成后,狀態欄的文本將被清除,功能區的“暫停”按鈕被“運行”按鈕取代,命令視窗顯示>>指示輸入的新命令將立即執行。
實際上,我希望在函式中間運行的代碼能夠具有在命令視窗中輸入新命令的等效效果,在當前執行的代碼完成后運行。
例如,考慮函式:
function testfun(x)
disp("Starting main execution with input " x);
pause(1)
disp("Completed main execution with input " x);
disp("Starting followup execution with input " x);
pause(1)
disp("Completed followup execution with input " x);
end
一個函式或腳本多次呼叫它(在額外disp呼叫的地方,可能還有其他未指定的耗時活動):
testfun(1)
disp("Done testfun(1).")
testfun(2)
disp("Done testfun(2).")
將導致輸出:
Starting main execution with input 1
Completed main execution with input 1
Starting followup execution with input 1
Completed followup execution with input 1
Done testfun(1).
Starting main execution with input 2
Completed main execution with input 2
Starting followup execution with input 2
Completed followup execution with input 2
Done testfun(2).
總共需要四秒鐘。另一種解決方案將導致輸出:
Starting main execution with input 1
Completed main execution with input 1
Done testfun(1).
Starting main execution with input 2
Completed main execution with input 2
Done testfun(2).
Starting followup execution with input 1
Completed followup execution with input 1
Starting followup execution with input 2
Completed followup execution with input 2
outputDone testfun(2)是最后出現的高優先級輸出結果,只需要 2 秒出現,而不是原來的 4 秒。
Is this possible? Alternatively, if I could allow execution to clear the current execution stack (as I could if interrupting the code with the debugger, then using dbstep out all the way up to the Base workspace, then calling new code from the command window) this would be a useful compromise even if it leaves open the possibility there are more function calls queued in the Base workspace. (The actual choice of workspace the code executes in doesn't matter too much, but stepping out of deeper nested workspaces would at least allow the remaining code queued within those workspaces to be completed before the workspace is destroyed.)
uj5u.com熱心網友回復:
感謝 MathWorks 的 Jan Simon,我所知道的最好的部分解決方案是觀察 MATLAB 視窗的實際狀態欄。這可以通過以下方式訪問:
statusbar = com.mathworks.mde.desk.MLDesktop.getInstance.getMainFrame.getStatusBar;
然后可以使用 檢索狀態欄中包含的文本statusbar.getText。當代碼正在執行時,文本包含“Busy”這個詞,當沒有任何東西在執行時它不包含,所以我可以使用邏輯來確定 MATLAB 當前正忙(注意其他事情的可能性,例如探查器,也將修改此文本的內容)。
Atimer可以輪詢此文本,因此在 MATLAB 的忙碌狀態結束后,回呼將在短時間內觸發(盡管不是立即,并且取決于我愿意輪詢介面的積極程度)。
這并不理想,因為它只是間接地從一個不參與應用程式控制的 UI 元素推斷忙碌狀態,并且可能不可靠,并且因為它依賴于重復輪詢,但在某些情況下它會比沒有。
將此應用到簡化的示例中,我們可以將任務分解為兩個函式,主要函式采用一個額外的引數t來接收要與之互動的計時器物件:
function testmain(x,t)
disp("Starting main execution with input " x);
pause(1)
disp("Completed main execution with input " x);
t.UserData.followups(end 1) = x;
end
function testfollowup(x)
disp("Starting followup execution with input " x);
pause(1)
disp("Completed followup execution with input " x);
end
定時器的回呼可以是:
function followupcallback(t,~)
if isempty(t.UserData.followups)
return
end
status = t.UserData.statusbar.getText;
if ~isempty(status) && contains(string(status),"Busy")
return
end
arrayfun(@testfollowup,t.UserData.followups);
t.UserData.followups = [];
t.stop
end
然后可以設定輪詢計時器:
t = timer( ...
"TimerFcn",@followupcallback, ...
"Period",0.25, ...
"ExecutionMode","fixedRate", ...
"UserData",struct( ...
"statusbar",com.mathworks.mde.desk.MLDesktop.getInstance.getMainFrame.getStatusBar, ...
"followups",[]));
t.start;
修改示例腳本以通過計時器:
testfun(1,t)
disp("Done testfun(1).")
testfun(2,t)
disp("Done testfun(2).")
結果輸出按預期重新排序。
uj5u.com熱心網友回復:
我認為你可以建立一個實際的作業佇列。為此,我在這里使用了一個全域變數,以便多個不同的函式可以添加到作業佇列中。我還使用嵌套函式將任意代碼和變數封裝到可以存盤和稍后運行的函式句柄中。
我仍然不清楚為什么這會有用,但它確實按照 OP 中的示例給出的順序處理事物。
initialize_work_queue
testfun(1)
disp("Done testfun(1).")
testfun(2)
disp("Done testfun(2).")
process_work_queue
disp("Done process_work_queue.")
function testfun(x)
disp("Starting main execution with input " x);
pause(1)
disp("Completed main execution with input " x);
function follow_up_work
disp("Starting followup execution with input " x);
pause(1)
disp("Completed followup execution with input " x);
end
global my_work_queue
my_work_queue{end 1} = @follow_up_work;
end
function initialize_work_queue
global my_work_queue
my_work_queue = {};
end
function process_work_queue
global my_work_queue
while ~isempty(my_work_queue)
func = my_work_queue{1};
my_work_queue(1) = [];
func();
end
end
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/361467.html
上一篇:MATLAB全域變數和腳本
