I am writing an indicator which draws certain objects in the chart. Upon removing the indicator (or changing timeframes or input settings) an OnDeinit() procedure is therefore called to clean up resources by - among freeing arrays and nullifying variables etc. - also remove the drawn objects from the chart. A stripped down code example for illustration is found below:
If you run the indicator above you will see a red trendline on the most recent bars, the purpose is simply to illustrate the problem. Should you choose to remove the indicator or change timeframe, the currently drawn trendlines are removed purposefully.
The problem with my indicator is that race conditions can occur when changing timeframe, such that the OnDeinit() call is called from the "old" indicator instance after the "new" indicator instance has already drawn. This leads to the erroneous behavior that the indicator does not always work smoothly when changing timeframe. To alleviate the problem I thought adding a random number to the names of the objects an indicator creates would be a proper solution, hence the
part. However, even though this works most of the time, it turns out that if I restart the terminal, the objects from beforehand are no longer deleted. This can be tried of course by using the above code.
So I am wondering what to do, is this a bug in the Metatrader platform? would it not be best to ensure that race conditions on the OnDeinit() procedure does not occur in the first place? And is there other, proper solutions for this problem?
Why don't you try
Did you chek void OnDeinit(const int reason)
I use construction like this. Create objects with "identif" in name.
A fix did exist, as the problem is:
So if one deletes all objects by the static identifier only in the OnInit() procedure, the chart is cleaned upon a terminal restart. So the solution is
Because that would delete objects drawn manually or by other indicators also, which is undesirable.
Edit: BTW. it would in any case also lead to a possible race condition.
What race conditions are you talking about ?
If you change timeframe or settings, OnDeinit() is called BEFORE OnInit() with the new settings/timeframe. I tried your indicator and doesn't have any problem. (MT5 build 1455).
Use it properly in place of your loop with StringFind() :
The race condition is a bit hard to obtain, but just setting the number of trendlines to 5000 (from 500 in the i=MathMax(...)) and adding printf statements at the entry and exits of the oncalculate and ondeinit methods gave me the following on the same build, multicore CPU:
DS 0 16:37:24.706 Bug (EURUSD,H1) Drawing done: EH 0 16:37:25.294 Bug (EURUSD,H1) Drawing: OO 0 16:37:25.319 Bug (EURUSD,H1) Drawing done: HG 0 16:37:25.699 Bug (EURUSD,H1) Drawing: HK 0 16:37:25.734 Bug (EURUSD,H1) Drawing done: CP 0 16:37:26.716 Bug (EURUSD,H12) Drawing: FD 0 16:37:26.766 Bug (EURUSD,H12) Drawing done: DQ 0 16:37:26.782 Bug (EURUSD,H1) Deinitializing: EJ 0 16:37:27.304 Bug (EURUSD,H1) Deinitializing done: EJ 0 16:37:27.304 Bug (EURUSD,H12) Drawing: QR 0 16:37:27.326 Bug (EURUSD,H12) Drawing done: CF 0 16:37:27.326 Bug (EURUSD,H12) Drawing: HN 0 16:37:27.349 Bug (EURUSD,H12) Drawing done:
So clearly here the new timeframe was started before the OnDeinit().
I was not aware of the ObjectsDeleteAll() overload that accepts a filtering substring.
Care to explain why you would need 5000 trendlines?
Drawing, as well as running mass printing will take some time to process.
Of course you can always increase the number until it crashes but do you really need that many ?
However if you are using the best option available which is ObjectsDeleteAll() with a prefix, it doesn't happen !
2016.11.10 21:49:49.304 160715 (EURUSD,M5) OnCalculate start2016.11.10 21:49:49.321 160715 (EURUSD,M5) OnCalculate end2016.11.10 21:49:51.271 160715 (EURUSD,M5) OnDeinit start2016.11.10 21:49:51.281 160715 (EURUSD,M5) OnDeinit end. 5000 Objects deleted.2016.11.10 21:49:51.285 160715 (EURUSD,H1) OnInit start2016.11.10 21:49:51.285 160715 (EURUSD,H1) OnInit end2016.11.10 21:49:51.285 160715 (EURUSD,H1) OnCalculate start2016.11.10 21:49:51.312 160715 (EURUSD,H1) OnCalculate end
5,000 objects deleted in 10 ms.
While with a loop (your original code), it takes 320 ms. (while the race condition doesn't always occurred).
2016.11.10 21:54:16.457 160715 (EURUSD,M5) OnDeinit start2016.11.10 21:54:16.778 160715 (EURUSD,M5) OnDeinit end. 5000 Objects deleted.
32 x faster.