www.gusucode.com > external 工具箱matlab源码程序 > external/interfaces/webservices/http/+matlab/+net/+http/+internal/ProgressReporter.m
classdef ProgressReporter < handle % This class is instantiated by HTTPConnector when the user specifies a % ProgressMonitorFcn in HTTPOptions and UserProgressMonitor is set. It saves a % reference to the user's ProgressMonitor and acts as link between C++ and the % user's ProgressMonitor. % % When a request is sent, HTTPConnector.m sets ProgressMonitor.Maximum to the % expected number of bytes to be sent and Direction to Request. C++ code then % calls out to the update() function to update progress, which determines % whether it's time to display or update the progress monitor based on % ProgressMonitor.interval. If so, it sets the user's ProgressMonitor.Value % to the number of bytes transferred. % % As soon as HTTPConnector receives the header of a ResponseMessage, it sets % Direction to Response, changes the Maximum, and then during transfer C++ calls % out to update() again. % % When transfer is all done, HTTPConnector destroys this object, which calls % ProgressMonitor.done() (but does not delete it). % Copyright 2015-2016 The MathWorks, Inc. properties (Access=private) ProgressMonitor % user's matlab.net.http.ProgressMonitor StartTime % datetime we should start reporting progress Started = false % true if started Cancel = false end properties (Dependent, GetAccess=private)%, ... %SetAccess=?matlab.net.http.internal.HTTPConnector) Maximum % the Content-Length, empty if unknown length Direction end methods function obj = ProgressReporter(pm) if nargin > 0 if pm.InUse error(message('MATLAB:http:MonitorInUse')); end obj.ProgressMonitor = pm; obj.Direction = matlab.net.http.MessageType.Request; pm.InUse = true; % The user's pm will call CancelFcn to cancel pm.CancelFcn = @(o,e)setCancel(obj); end function setCancel(obj) % On cancel, just set a flag that the next update call will look at obj.Cancel = true; end end end methods function ok = update(obj, value) % Called from the C++ InterruptibleStreamCopier to update progress. % value - number of bytes transferred % ok - false if user's ProgressMonitor called the cancel function assert(~isempty(obj.StartTime)); % expect Direction was set before this % Don't set Value after start of transfer until Interval seconds have % elapsed sicne the last change of direction. if obj.Started || datetime('now') > obj.StartTime obj.ProgressMonitor.Value = value; ok = ~obj.Cancel; obj.Started = true; if ~ok obj.done(); end else ok = true; end end function set.Direction(obj, value) obj.ProgressMonitor.Direction = value; interval = obj.ProgressMonitor.Interval; if isempty(interval) interval = 2; end validateattributes(interval, {'numeric'}, ... {'scalar', 'real', 'nonnegative'}, 'ProgressMonitor', 'Interval'); % TBD implement interval between update calls. This requires % communicating the interval to the HTTPConnectionAdapter where the % actual timing will be done (in the InterruptibleStreamCopier). if ~obj.Started % On each change of direction, if ProgressMonitor has not yet been % called to update, postpone first setting of value until interval % seconds have elapsed. One it is started, we don't wait for % interval. obj.StartTime = datetime('now') + seconds(interval); end end function set.Maximum(obj, value) obj.ProgressMonitor.Max = value; end function delete(obj) obj.done(); end end methods (Access=private) function done(obj) if ~isempty(obj.ProgressMonitor) && isvalid(obj.ProgressMonitor) obj.ProgressMonitor.done(); obj.ProgressMonitor.InUse = false; end end end end