我想每隔30分钟运行一个函数。每次函数运行时,它将接受不同的输入。假设我想跑这100次。函数为查找天气,输入为location1、location2、location3、.、location100
我试过:
for a = 1:100
t = timer;
t.StartDelay = 30*60*(a-1)
t.TimerFcn = @(scr, event) run('lookupweather');
start(t)
end 这里的问题是我无法找到输入位置信息的方法。如果我尝试了查找天气(Location1),代码就失败了。当然,如果没有位置输入,则查找天气函数就会失败。有人能帮忙吗?
编辑:我意识到我可以做固定的间隔
t = timer;
t.Period = 30*60;
t.TasksToExecute = 100;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = @(src, event) run('lookupweather');
start(t)不过,我仍然不知道如何将位置信息输入到我的函数lookupweather中。
发布于 2019-07-19 23:12:45
您需要使用单元格数组声明计时器回调函数,如下所示:
location_index = 1;
t = timer;
t.Period = 1; %30*60;
t.TasksToExecute = 5; %100;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = {@timer_callback, location_index};
start(t);
process_locations = true;
while process_locations
% . . .
end
stop(t);
delete(t);
function timer_callback(obj, event, location_index)
fprintf("Location index = %03d\n", location_index);
end您还可能需要使用位置的一维矢量(或数组),如下所示:
locations = zeros(1, 100);
t = timer;
t.Period = 1; %30 * 60;
t.TasksToExecute = 5; %100;
t.ExecutionMode = 'fixedRate';
%t.TimerFcn = {@timer_callback2};
t.TimerFcn = {@timer_callback3, locations};
start(t);
process_locations = true;
while process_locations
% . . .
end
stop(t);
delete(t);
function timer_callback2(obj, event)
persistent location_index;
if isempty(location_index)
location_index = 1;
end
fprintf("Location index = %03d\n", location_index);
location_index = location_index + 1;
end
function timer_callback3(obj, event, locations)
persistent location_index
if isempty(location_index)
location_index = 1;
end
locations(location_index) = 12.3; % Get value from temperature sensor.
fprintf("locations(%03d) = %f\n", location_index, locations(location_index));
location_index = location_index + 1;
end第4版
这使用在计时器回调中修改的全局结构。考虑将其封装到处理程序类或嵌套函数中,以避免使用全局变量。
clear all;
clc;
number_of_iterations = 10; % 100
number_of_locations = 5;
% Create a global struct for the data.
% Consider encapsulating in a class rather than using a global.
global temperature_data;
temperature_data = struct("IterationIndex", 1, "Processed", false, "Locations", zeros(number_of_iterations, number_of_locations));
t = timer;
t.Period = 1; %30 * 60;
t.TasksToExecute = number_of_iterations;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = {@TimerCallback4};
start(t);
while temperature_data.Processed == false
% . . .
% Yield some processing time.
time_delay = t.Period * 1000 / 10;
java.lang.Thread.sleep(time_delay);
end
stop(t);
delete(t);
function TimerCallback4(obj, event)
global temperature_data;
% Cycle through locations.
for location_index = 1:5
% Get value from temperature sensor.
temperature_data.Locations(temperature_data.IterationIndex, location_index) = 100 * rand;
fprintf("temperature_data(%03d, %d) = %5.2f\n", temperature_data.IterationIndex, location_index, temperature_data.Locations(temperature_data.IterationIndex, location_index));
end
% Test for completion of processing.
if temperature_data.IterationIndex >= size(temperature_data.Locations, 1)
temperature_data.Processed = true;
else
temperature_data.IterationIndex = temperature_data.IterationIndex + 1;
end
end第4版结果
TimerCallback4() 0.058
TimerCallback4() 1.023
TimerCallback4() 2.033
TimerCallback4() 3.042
TimerCallback4() 3.961
TimerCallback4() 4.975
TimerCallback4() 5.982
TimerCallback4() 6.990
TimerCallback4() 8.002
TimerCallback4() 9.008
10.7889 18.2228 9.9095 48.9764 19.3245
89.5892 9.9090 4.4166 55.7295 77.2495
31.1940 17.8982 33.8956 21.0146 51.0153
90.6364 62.8924 10.1534 39.0855 5.4617
50.1283 43.1721 99.7560 81.1603 48.5652
89.4448 13.7547 39.0005 92.7356 91.7494
71.3574 61.8337 34.3288 93.6027 12.4774
73.0585 64.6477 83.3152 39.8282 74.9822
83.5221 32.2460 55.2262 97.9129 54.9309
33.0424 61.9472 36.0637 75.6510 41.3901第5版
此版本使用句柄类。它可以同步处理,也可以异步处理。
Test.m
clear all;
clc;
% Define the settings.
number_of_iterations = 10; % 100
number_of_locations = 5;
period = 1; % 30 * 60 % Seconds.
% Create the object with required settings.
temperature_processor = TemperatureProcessor(number_of_iterations, number_of_locations, period);
% Do the process synchronously.
temperature_processor.ProcessSync();
disp(temperature_processor.Locations);
% Do the process asynchronously.
temperature_processor.IsProcessed = false;
temperature_processor.ProcessAsync();
while temperature_processor.IsProcessed == false
% Do other stuff.
% . . .
% Yield some processing time.
%pause(0.001);
java.lang.Thread.sleep(1); % milliseconds.
end
disp(temperature_processor.Locations);
% Delete the object.
delete(temperature_processor);TemperatureProcessor.m
classdef TemperatureProcessor < handle
properties
IsProcessed = false;
Locations;
end
properties (Access = private)
% Define default values.
NumberOfIterations = 100;
NumberOfLocations = 5;
Period = 30 * 60; % Seconds.
AsyncIterationIndex = 1;
AsyncTimer;
end
methods
% Constructor.
function obj = TemperatureProcessor(number_of_iterations, number_of_locations, period)
fprintf("obj.TemperatureProcessor() constructor\n");
if nargin == 3
obj.NumberOfIterations = number_of_iterations;
obj.NumberOfLocations = number_of_locations;
obj.Period = period;
end
obj.Locations = zeros(obj.NumberOfIterations, obj.NumberOfLocations);
end
% Destructor.
function delete(obj)
fprintf("obj.delete() destructor\n");
try
stop(obj.AsyncTimer);
delete(obj.AsyncTimer);
catch
end
end
function ProcessSync(obj)
fprintf("obj.ProcessSync()\n");
iteration_index = 1;
the_timer = timer;
the_timer.Period = obj.Period;
the_timer.TasksToExecute = obj.NumberOfIterations;
the_timer.ExecutionMode = 'fixedRate';
the_timer.TimerFcn = {@TimerCallbackSync};
tic;
start(the_timer);
wait(the_timer);
delete(the_timer);
function TimerCallbackSync(timer_obj, timer_event)
fprintf("obj.Process.TimerCallbackSync() %0.3f\n", toc);
% Cycle through locations.
for location_index = 1:obj.NumberOfLocations
% Get value from temperature sensor.
obj.Locations(iteration_index, location_index) = 100 * rand;
fprintf("obj.Locations(%03d, %d) = %5.2f\n", iteration_index, location_index, obj.Locations(iteration_index, location_index));
end
% Test for completion of processing.
if iteration_index >= obj.NumberOfIterations
obj.IsProcessed = true;
else
iteration_index = iteration_index + 1;
end
end
end
function ProcessAsync(obj)
fprintf("obj.ProcessAsync()\n");
try
stop(obj.AsyncTimer);
delete(obj.AsyncTimer);
catch
end
obj.AsyncIterationIndex = 1;
obj.AsyncTimer = timer;
obj.AsyncTimer.Period = obj.Period;
obj.AsyncTimer.TasksToExecute = obj.NumberOfIterations;
obj.AsyncTimer.ExecutionMode = 'fixedRate';
obj.AsyncTimer.TimerFcn = {@obj.TimerCallbackAsync};
tic;
start(obj.AsyncTimer);
end
function TimerCallbackAsync(obj, timer_obj, timer_event)
fprintf("obj.Process.TimerCallbackAsync() %0.3f\n", toc);
% Cycle through locations.
for location_index = 1:obj.NumberOfLocations
% Get value from temperature sensor.
obj.Locations(obj.AsyncIterationIndex, location_index) = 100 * rand;
fprintf("obj.Locations(%03d, %d) = %5.2f\n", obj.AsyncIterationIndex, location_index, obj.Locations(obj.AsyncIterationIndex, location_index));
end
% Test for completion of processing.
if obj.AsyncIterationIndex >= obj.NumberOfIterations
try
stop(obj.AsyncTimer);
delete(obj.AsyncTimer);
catch
end
obj.IsProcessed = true;
else
obj.AsyncIterationIndex = obj.AsyncIterationIndex + 1;
end
end
end
end第5版结果
obj.TemperatureProcessor() constructor
obj.ProcessSync()
obj.Process.TimerCallbackSync() 0.051
obj.Process.TimerCallbackSync() 1.029
obj.Process.TimerCallbackSync() 2.026
obj.Process.TimerCallbackSync() 3.025
obj.Process.TimerCallbackSync() 4.034
obj.Process.TimerCallbackSync() 5.024
obj.Process.TimerCallbackSync() 6.023
obj.Process.TimerCallbackSync() 7.023
obj.Process.TimerCallbackSync() 8.023
obj.Process.TimerCallbackSync() 9.023
obj.ProcessAsync()
obj.Process.TimerCallbackAsync() 0.009
obj.Process.TimerCallbackAsync() 1.005
obj.Process.TimerCallbackAsync() 2.004
obj.Process.TimerCallbackAsync() 3.005
obj.Process.TimerCallbackAsync() 4.007
obj.Process.TimerCallbackAsync() 5.005
obj.Process.TimerCallbackAsync() 6.005
obj.Process.TimerCallbackAsync() 7.005
obj.Process.TimerCallbackAsync() 8.005
obj.Process.TimerCallbackAsync() 9.005
obj.delete() destructor发布于 2019-07-21 07:44:08
对于一般的解决方案,您可以创建自己的事件和侦听器类。
例如,创建一个名为.m的新sampleEvent.m文件,您可以在其中编写
classdef weather < handle
events
lookup_timedriven
end
methods
function lookup(self)
notify(self,'lookup_timedriven')
end
%%%% optional
function self = weather(self)
t = timer;
t.StartDelay = 1; % leave some time for event handler to be created
t.TimerFcn = @()[]; % You can't create a true empty function_handle unless you have a do nothing function in your library.
start(t)
for a = 0:99 % the weather calls
t = timer;
t.StartDelay = 30*60*a;
t.TimerFcn = @self.lookup;
start(t)
end
end
%%%%
end
end和另一个名为.m的sampleListener.m文件,您在其中编写
classdef sampleListener < handle
methods
function sampleListener(weather_obj)
lh = addlistener(weather_obj,'lookup_timedriven',@sampleListener.handleEvnt);
end
end
methods (Static) % static is a must. Because addlistener calls the function without instantiating an object
function handleEvnt(src,~)
cellfun(@lookupweather, cellOfLocations, 'UniformOutput', false);
end
end
end假设函数lookupweather采用1个参数并将数据正确地存储在幕后,而cellOfLocations是“位置”的单元格数组。每当事件被触发时,您可以用想要做的任何事情来替换cellfun(@lookupweather, cellOfLocations, 'UniformOutput', false)。Matlab允许您使用特定事件数据。
如果您不熟悉Maltab中的对象,请参见这篇数学文章。基本上,在启动任何定时例程之前,您需要用
weatherEvent = weather;
weatherEventHandler = sampleListener(weather);现在,您只需要通过每30分钟或以其他方式调用weather.lookup来触发事件。
实际上,如果希望在后台运行timer,可以使用weatherlookup。您已经知道timer是如何工作的,在我前面的示例中,weather.lookup不接受任何参数。所以你遇到的问题不会发生在这里。
您可以在单独的.m文件中或直接在wheather类中实现计时代码。如果希望计时器自动启动,可以在weather的构造函数中定义方法,这就是我在示例中展示的。
一些评论:
使用100个变量的weatherlookup规范是没有意义的。如果这是由于Matlab本机获取未指定数量的“位置”,则只需一次使用1 "location“调用weatherlookup,并使用cellfun。
我也不确定timer的问题是否是Matlab真正的限制。.TimerFcn字段可以是任何函数句柄.换句话说,您应该尝试将我的示例中的@self.lookup替换为直接向上的@()notify(self,'lookup_timedriven')。
另外,你似乎想做的是用谷歌AppScript + GoogleSheet更好地实现。Google提供了时间驱动的触发器,没有任何额外的东西,它将在云中为您运行程序(只要您不太频繁地运行;一次非常30分钟就可以了)。
https://stackoverflow.com/questions/57120178
复制相似问题