タイマー キューの競合への対処
複数実行のシナリオにおけるビジー時間では、タイマーは、コールバック関数の前のキューにある実行が終了する前に、タイマー コールバック関数 (TimerFcn) を MATLAB® の実行キューに追加しなければならない場合があります。BusyMode プロパティが動作に影響するのは、ExecutionMode プロパティが FixedRate に設定されている場合のみです。ExecutionMode が他の値の場合は、常に前の実行の完了を基準とする遅延が実行間で発生するため、タイマー コールバック関数の実行がオーバーラップして試行されることはありません。
timer オブジェクトで、次のいずれかのモードを使用するように BusyMode プロパティを設定して、このシナリオを扱う方法を決定できます。
ドロップ モード (既定)
BusyMode プロパティの値として 'drop' を指定する場合、timer オブジェクトは、キューが空の場合のみにタイマー コールバック関数を実行キューに追加します。実行キューが空でない場合、timer オブジェクトはコールバックの実行をスキップします。
たとえば、この mytimer.m に示されるように、1 秒間隔のタイマーを作成するがコールバックで少なくとも 1.6 秒必要であるとします。
function mytimer()
t = timer;
t.Period = 1;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = @mytimer_cb;
t.BusyMode = 'drop';
t.TasksToExecute = 5;
t.UserData = tic;
start(t)
end
function mytimer_cb(h,~)
timeStart = toc(h.UserData)
pause(1.6);
timeEnd = toc(h.UserData)
end次の表では、タイマーが実行キューを管理する方法を説明します。
おおよその経過時間 (秒) | タイマーのアクション | 実行中の関数 |
|---|---|---|
| 0 (タイマー開始) | TimerFcn をタイマーのキューに追加します。 | なし |
| 0 + キュー遅延 | アクションはありません。 | TimerFcn の最初の呼び出し |
| 1 | TimerFcn の 2 番目の呼び出しのキューへの追加を試みます。TimerFcn の最初の呼び出しがまだ実行中であるため、2 番目の呼び出しは破棄されます。 | |
| 1.6 | TimerFcn の 2 番目の呼び出しをキューに追加します。 | なし |
| 1.6 + キュー遅延 | アクションはありません。 | TimerFcn の 2 番目の呼び出し |
| 2 | TimerFcn の 3 番目の呼び出しのキューへの追加を試みます。TimerFcn の 2 番目の呼び出しがまだ実行中であるため、3 番目の呼び出しは破棄されます。 | |
| 3.2 | TimerFcn の 3 番目の呼び出しをキューに追加します。4 番目の呼び出しは破棄されます。 | なし |
| 3.2 + キュー遅延 | TimerFcn の 4 番目の呼び出しのキューへの追加を試みます。TimerFcn の 3 番目の呼び出しがまだ実行中であるため、4 番目の呼び出しは破棄されます。 | TimerFcn の 3 番目の呼び出し |
| 3.2 | ||
| 4.8 | TimerFcn の 4 番目の呼び出しをキューに追加します。5 番目の呼び出しは破棄されます。 | なし |
| 4.8 + キュー遅延 | TimerFcn の 5 番目の呼び出しのキューへの追加を試みます。TimerFcn の 4 番目の呼び出しがまだ実行中であるため、5 番目の呼び出しは破棄されます。 | TimerFcn の 4 番目の呼び出し |
| 4.8 | ||
| 6.4 | TimerFcn の 5 番目の呼び出しをキューに追加します。 | なし |
| 6.4 + キュー遅延 | TasksToExecute の値が 5 であるため、mytimer に実行するコールバックはもうありません。 | TimerFcn の 5 番目の呼び出し |
| 8 |
エラー モード
BusyMode プロパティの 'error' モードは、'drop' モードと同様です。両方のモードとも、タイマーは実行キューのコールバックのインスタンスを 1 つのみ使用できます。'error' モードでは、キューが空でない場合、タイマーは ErrorFcn プロパティを使用して指定した関数を呼び出してから、処理を停止します。現在実行中のコールバック関数は完了しますが、キューの中のコールバックは実行されません。
たとえば、(前の節で説明した) mytimer.m を変更してエラー処理関数を含め、BusyMode を 'error' に設定します。
function mytimer()
t = timer;
t.Period = 1;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = @mytimer_cb;
t.ErrorFcn = @myerror;
t.BusyMode = 'error';
t.TasksToExecute = 5;
t.UserData = tic;
start(t)
end
function mytimer_cb(h,~)
timeStart = toc(h.UserData)
pause(1.6);
timeEnd = toc(h.UserData)
end
function myerror(h,~)
disp('Reached the error function')
end次の表では、タイマーが実行キューを管理する方法を説明します。
おおよその経過時間 (秒) | タイマーのアクション | 実行中の関数 |
|---|---|---|
| 0 (タイマー開始) | TimerFcn をタイマーのキューに追加します。 | なし |
| 0 + キュー遅延 | アクションはありません。 | TimerFcn の最初の呼び出し |
| 1 | TimerFcn の 2 番目の呼び出しのキューへの追加を試みます。TimerFcn の最初の呼び出しがまだ実行中であるため、myerror は TimerFcn の最初の呼び出しが完了した時点でキューに入れられます。 | |
| 1.6 | myerror をキューに追加します。 | なし |
| 1.6 + キュー遅延 | アクションはありません。 | myerror を呼び出し |
キュー モード
'queue' を指定すると、timer オブジェクトは、タイマー コールバック関数の次の実行をキューに入れる前に、現在の実行コールバック関数が終了するまで待機します。
'queue' モードでは、timer オブジェクトは実行間の平均時間を Period プロパティに指定された時間に等しくしようとします。timer オブジェクトがタイマー関数コールバックの実行間 Period プロパティに指定された時間より長く待機しなければならない場合、時間調整のために続く実行の期間を短縮します。
たとえば、(前の節で説明した) mytimer.m を変更して BusyMode を 'queue' に設定します。
function mytimer()
t = timer;
t.Period = 1;
t.ExecutionMode = 'fixedRate';
t.TimerFcn = @mytimer_cb;
t.ErrorFcn = @myerror;
t.BusyMode = 'queue';
t.TasksToExecute = 5;
t.UserData = tic;
start(t)
end
function mytimer_cb(h,~)
timeStart = toc(h.UserData)
pause(1.6);
timeEnd = toc(h.UserData)
end
function myerror(h,~)
disp('Reached the error function')
end次の表では、タイマーが実行キューを管理する方法を説明します。
| おおよその経過時間 (秒) | タイマーのアクション | 実行中の関数 |
|---|---|---|
| 0 | コールバックの最初の実行を開始します。 | なし |
| 0 + キュー遅延 | アクションはありません。 | TimerFcn の最初の呼び出し |
| 1 | コールバックの 2 番目の実行の開始を試みます。最初の実行が完了しておらず、実行キューは空のままです。 | |
| 1.6 | 2 番目のコールバックがタイマーのキューに追加されます。 | なし |
| 1.6 + キュー遅延 | アクションはありません。 | TimerFcn の 2 番目の呼び出し |
| 2 | コールバックの 3 番目の実行の追加を試みます。2 番目の実行が完了しておらず、実行キューは空のままです。 | |
| 3 | コールバックの 4 番目の実行の開始を試みます。2 番目の実行が完了しておらず、実行キューは空のままです。 | |
| 3.2 | 2 番目のコールバックの実行を終了します。3 番目と 4 番目のコールバックがタイマーのキューに追加され、3 番目が実行されます。実行キューには 4 番目のコールバックが格納されます。 | なし |
| 3.2 + キュー遅延 | アクションはありません。 | TimerFcn の 3 番目の呼び出し |
| 4 | コールバックの 5 番目の最後の実行の開始を試します。3 番目の実行は完了していません。実行キューには 4 番目のコールバックが格納されます。 | |
| 4.8 | 3 番目のコールバックの実行を終了します。5 番目の実行がタイマーのキューに追加され、4 番目が実行されます。実行キューには 5 番目のコールバックが格納されます。 | なし |
| 4.8 + キュー遅延 | TasksToExecute の値が 5 であるため、mytimer に実行するコールバックはもうありません。 | TimerFcn の 4 番目の呼び出し |
| 6.4 | なし | |
| 6.4 + キュー遅延 | TimerFcn の 5 番目の呼び出し | |
| 8 |