2012-05-07 9 views
1

これは、this questionと多少関連していますが、あまり関係ありません。MATLAB - タイマが関与しているときにオブジェクトがクリアされない

私は二つのクラス、FunctionWrapperTimerWrapperあります

classdef FunctionWrapper < handle 
    methods 
     function Fcn(obj) 
      disp('FunctionWrapper.Fcn was called!'); 
     end 
    end 
end 

classdef TimerWrapper < handle 
    properties 
     Timer 
    end 

    methods 
     function obj = TimerWrapper(other_object) 
      obj.Timer = timer; 
      set(obj.Timer, 'Period', 1); 
      set(obj.Timer, 'ExecutionMode', 'fixedSpacing'); 
      set(obj.Timer, 'TimerFcn', @(event, data) other_object.Fcn); 
     end 

     function start(obj) 
      start(obj.Timer); 
     end 

     function stop(obj) 
      stop(obj.Timer); 
     end 

     function delete(obj) 
      disp('destructor called!'); 
      delete(obj.Timer); 
     end 
    end 
end 

は、私がコマンドウィンドウに次のコードを実行言う:

>> F = FunctionWrapper; 
>> T = TimerWrapper(F); 
>> clear T %# T's destructor not called 
>> timerfind %# just to verify that no, the destructor was never called 

    Timer Object: timer-1 

    Timer Settings 
     ExecutionMode: fixedSpacing 
      Period: 1 
      BusyMode: drop 
      Running: off 

    Callbacks 
      TimerFcn: @(event,data)other_object.Fcn 
      ErrorFcn: '' 
      StartFcn: '' 
      StopFcn: '' 

ここで何が起こっていますか?私はtimerオブジェクトを手動で削除する必要があることを知っていますが、私はTimerWrapperのデストラクタで扱われると思いました。 Amro's ugly but straightforward workaround to overload the clear commandを使用しないと、作業場からclear Tへの道はありますか?さらに、Tを参照するものは何もないので、なぜそのリファレンスが存在しますか? (デストラクタが呼び出されないという事実は、この事実を意味しています。)これはタイマオブジェクト自体に埋め込まれていますか?

答えて

2

t = TimerWrapper; f = functions(t.Timer.TimerFcn); f.workspace(2)と入力すると、コールバックに使用される匿名関数のワークスペースにTimerWrapperオブジェクトへの参照が含まれていることがわかります。だから、そこには循環参照の種類がありますが、それはclearによって取り上げられません。

どのように設定したら、デストラクタを明示的に呼び出してからclearを呼び出して、T(およびその基礎となるタイマーオブジェクト)を削除できます。

T.delete 
clear T 

cleardeleteとの違いは、一種の(とにかく、私には)混乱しています。あなたが見つけたように、clearはデストラクタを明示的に呼び出さない。ワークスペースからという名前がTだけ削除されます。そのため、Tとその基になるタイマーは、その時点ではまだ存在しています。それでも存在していたものへの参照が含まれていなかった場合、MATLABはデストラクタの呼び出しを含めてTを適切に削除します。つまり、タイマーには(コールバック内の)Tへの参照が含まれているため、タイマー(したがってTも同様)は削除されません。

あなたはtimerfindallと(ワークスペースに名前を持っていないにも関わらず)、それを見つけることができる、と明示的に

tmrs = timerfindall; 
delete(tmrs); 

を使用して、それを自分で削除した場合、あなたはTが正しくなくなっていることがわかります。

これはバグだと私は確信していませんが、かなり混乱していますが、cleardeleteの区別はおそらくもっとよく書かれています。

回避策としては、deleteを明示的に呼び出すのは大きな苦労ではありませんが、間違いなくclearに電話した場合は、これをもう少し掃除するのが苦痛です。メッセージ#4ではなく、リンク先のthreadからのメッセージ#5の提案がより一般的で堅牢になると思います。

私はあなたがにリンクされている別のスレッドでsuggests @Amro方法でclearに過負荷をかけなければならないとは思わない:これが機能かもしれないが、あなたが明示的clear Tを呼び出す場合、あなたはまだあなたがclear allを呼び出す場合トラブルに巻き込まれる、またはclear variablesあり。 (私はちょうど今試していませんが、これらの構文はclearだと思うので、ワークスペース内のものをループさせずにclearを呼び出してください。代わりに、内部MATLABワークスペースオブジェクトのclearメソッドを呼び出します。速く混乱する)。

+0

私は実際に 'F'への参照を完全に削除し、これをテストするためにコールバックに' disp'を使用しました。それでも、それ自体は適切にクリアされません。 –

+0

しかし、T.deleteと入力し、その後にクリアTを入力すると、正しく動作しますか? –

+0

はい、そうです。これは正しい方法ですが、私のコードベースは巨大で、私のユーザ(実際にはほとんどのMATLABユーザ)は、 'delete'と' clear'が2つの異なることを全く知らないのです。とにかく、私は 'TimerFcn'を持っているとなぜこの動作が起こるのか理解しようとしています(これはバグではないと思います)。 –

0

タイマーのコールバックがデフォルト以外の値に設定されている可能性があります。 A proposed workaround(リンクされたスレッドのメッセージ#4を参照)は、startメソッドが呼び出されたときにのみコールバック関数を設定し、stopメソッドが呼び出されたときにnullに設定することです。

関連する問題