2018年11月10日土曜日
[MQL4] OnTick() と OnTimer() は同一スレッドで動いている
@MetaTrader 4.00 Build 1090 Expert Adviser の `OnTick()` で何か重たい処理をしているとき ### 確認環境 以下のような EA を作成し、タイミングをいろいろ変えて確認してみました。 ```mq4 `title: "Experts/ThreadTest.mq4"; #property strict static uint count = 0; int OnInit() { //--- create timer EventSetTimer(1); // 1秒(本来こんなに高頻度で呼ぶべきではない) return(INIT_SUCCEEDED); } void OnDeinit(const int reason) { //--- destroy timer EventKillTimer(); } void OnTick() { count++; printf("OnTick %u start", count); Sleep(3000); // 3秒待つ printf("OnTick %u end", count); } void OnTimer() { Print("OnTimer"); } ```、`OnTimer()` はどのように処理されるのか、調べてみました。 結論から言うと、以下のような動作をするようです。 (同一スレッド上で動いているか、少なくとも排他されている。) - `OnTick()` の処理中に `OnTimer()` のタイミングが来た場合、`OnTick()` 終了直後に`OnTimer()`が実行される(`OnTimer()` はペンディングされる) - ただし、2回以上ペンディングされたとしても、`OnTick()` 終了直後に実行される `OnTimer()` は1回のみ - ペンディングされたとしても、`OnTimer()` が呼ばれるタイミングには影響しない(`EventSetTimer()` が呼ばれた時点から指定間隔で呼ばれ続ける ) この動作、逆の場合も当てはまるようです。 つまり、`OnTimer()` で重たい処理をしていると、その間に呼ばれるはずだった `OnTick()` が無視されることになります 。 また、`OnTick()` で重たい処理をしていても、同じように `OnTick()` が無視されます。 `OnTick()` や `OnTimer()` ではなるべく重たい処理をしないようにすべきですね。 かつ `OnTimer()` の呼び出し頻度は少なめに。