How to interrupt file operations with a GUI callback function?

3 vues (au cours des 30 derniers jours)
WorkerBee
WorkerBee le 18 Déc 2021
Commenté : WorkerBee le 20 Déc 2021
Hi –
I’m running MATLAB 2019b and Windows 10.
I’m building a GUI in the App Designer, and I have a “Start” button a “Cancel” button and a TextArea control, among other things, in the GUI. When the user clicks the start button, it invokes a method of a custom class that starts importing a list of .csv files with the MATLAB readtable function. The individual files being imported are rather large (occasionally upwards of 500mb), so readtable takes somewhere between 10-30 seconds to import each file.
I’ve set the app up to give the user an update each time a file finishes importing (e.g. “File 1 of 10 imported”). These updates are displayed in the TextArea control on the GUI.
If the user clicks the cancel button while the data importation function is going, it sets a flag in a persistent variable within the custom class. The data import function checks the persistent variable each time before it starts to import a new file, and if it sees that the user has clicked cancel it will drop out of the loop. This works perfectly, but the data import function can only check the cancel flag once every 10-30 seconds because it’s waiting for readtable to finish.
I would like to give the user some indication that the cancel button has performed its function so I can avoid things like impatient users ending tasks via the task manager. Ideally, as soon as the user clicks cancel, a message would be printed to the TextArea that says “Cancelling operation…”, then readtable can finish what its working on at its leisure. However, I can’t seem to get the cancel button callback function to interrupt the readtable function, although it will interrupt the data import function as soon as readtable finishes. That means I have a 10-30 second delay between when the user clicks cancel and when they see some response from the GUI.
Both the start and cancel buttons are configured as interruptible in the app designer properties, if that has any relevance.
Anyone out there have a good idea of how to solve this problem?
Here’s some (vastly simplified) example code:
%% public functions from GUI app %%
function PrintMessage(app, Message)
% prints the provided message to a TextArea control in the GUI
app.MessageLogTextArea.Value = [Message newline app.MessageLogTextArea.Value];
drawnow
end
%% Private functions from GUI app %%
function StartButtonPushed(app, event)
% start button callback function
% reset the cancel flag to false
MyDataClass.SetGetCancelFlag(false);
% start the data import function
ImportData(app.MyDataClassObject, @(Message)PrintMessage(app,Message));
end
function CancelButtonPushed(app, event)
% cancel button callback function
% inform user that the cancellation process has started
PrintMessage(app, 'Cancelling operation...');
% set the cancel flag to true
MyDataClass.SetGetCancelFlag(true);
end
%% MyDataClass definition %%
classdef MyDataClass < handle
properties
ImportFileList (:,1) cell
ImportedData (:,1) cell
end
methods
function MyDataClassObject = MyDataClass
% constructor method
MyDataClassObject.ImportedData = cell.empty(0,1);
end
function ReturnValue = SetGetCancelFlag(NewFlagValue)
% sets or returns the value of the cancel flag
persistent CancelFlag
if nargin
CancelFlag = NewFlagValue;
end
if isempty(CancelFlag)
CancelFlag = false;
end
ReturnValue = CancelFlag;
end
function ImportData(MyDataClassObject, PrintFunction)
% imports data from .csv files using readtable
NumberOfFiles = size(MyDataClassObject.ImportFileList,1);
for Counter = 1:NumberOfFiles
% check if user cancelled the operation
if MyDataClass.SetGetCancelFlag()
PrintFunction('Operation cancelled by user.');
return
end
% import the next file
ImportedTable = readtable(MyDataClassObject.ImportedFileList{Counter});
MyDataClassObject.ImportedData = [MyDataClassObject.ImportedData; {ImportedTable}];
% update the user
PrintFunction(['File ' num2str(Counter) ' of ' num2str(NumberOfFiles) ' imported.']);
end
end
end
end

Réponse acceptée

Voss
Voss le 18 Déc 2021
If for whatever reason you cannot follow either of @Walter Roberson's suggestions in his answer, it might be worthwhile to consider replacing the call to readtable with some code of your own which can periodically query the state of CancelFlag and abort if necessary. It will likely be slower than readtable (probably much slower, but not necessarily, because the code only needs to support the specific format(s) of csv files your program needs to support), but it would allow the opportunity to respond more quickly to the Cancel button press. It will be a tradeoff between the speed of loading the files and the responsiveness of cancelling at will.
Again, a separate thread or parallel processing is best, but if those are not feasible, then writing your own code to do what readtable does may be worth thinking about, because otherwise I don't know how you would do it.
  2 commentaires
Walter Roberson
Walter Roberson le 19 Déc 2021
For example you could potentially use textscan() with a specific format, and specify a repetition count after the format, so it only processes that many times in one call.
WorkerBee
WorkerBee le 20 Déc 2021
Appreciate the suggestions guys - both are good ideas. Ideally, the I would use the thread option, but since a software upgrade isn't on the table for the near term, that rules that option out.
Looks like I'll be writing my own version of readtable...lucky me :)

Connectez-vous pour commenter.

Plus de réponses (1)

Walter Roberson
Walter Roberson le 18 Déc 2021
Modifié(e) : Walter Roberson le 18 Déc 2021
R2021b or later, you could put the reading operation into a background thread. Which you could potentially even cancel()
In your r2019b release, Parallel Computing toolbox would permit the same thing.

Catégories

En savoir plus sur Variables dans Help Center et File Exchange

Produits


Version

R2019b

Community Treasure Hunt

Find the treasures in MATLAB Central and discover how the community can help you!

Start Hunting!

Translated by