Seeking solution to an infinite loop that causes MT4 hang with ‘Not responding’ error.

 

Hi,

ChartSync indicator is supposed to do this:

Objects drawn on one chart automatically appear on other charts of the same symbol. This allows multi time-frame marking up of charts simultaneously, without having to manually save and load templates.

Example

If 3 EURUSD charts are open H1, M15 and M5.

If Chart Sync is applied to one chart, anything drawn on this chart will appear on the other two.

If Chart Sync is applied to all 3 charts then whatever is drawn on any of the charts will appear on the others.

Details

The small arrow in the bottom right corner of the chart indicates that Chart Sync is active and all changes will be reflected in other charts of the same symbol in this profile.

Chart Sync works on charts of the same symbol only in the current profile. When switching to a different profile, such as market overview, these charts will not have had objects updated.

Please take into account, objects sync on create, delete, edit and move events. When opening a new chart, old objects from other charts will only appear if one of those operations occurs to the object. (Thus open all required charts before drawing).

The attached MQL5 version works perfectly if you want to see it in action.

 

However the MQL4 version causes an infinite loop problem resulting in MT4 hanging with error ‘Not responding’

This is the MQL4 code:

// Chart_Sync_v2.mq4

// Idea & money: RogH, https://www.mql5.com/en/users/rogh
// Code: f2011, https://www.mql5.com/en/job/new?prefered=f2011

// 8.08.2014 15:00


#property version "1.20"
#property copyright "f2011"
#property strict

#property indicator_chart_window

#property indicator_buffers     0
#property indicator_plots               0



input int               Timer_Seconds = 3;                                              // Chart redraw frequency (seconds)
input color     Master_Color = clrSteelBlue;    // 'Master' sign color
input int               Master_Size = 12;                                                       // 'Master' sign font size



int OnInit() {
        ChartSetInteger(0, CHART_EVENT_OBJECT_DELETE, true);
        ChartSetInteger(0, CHART_EVENT_OBJECT_CREATE, true);
        ChartSetInteger(0, CHART_EVENT_MOUSE_MOVE, true);
        
        ObjectCreate("Chart_Sync_ON", OBJ_LABEL, 0, 0, 0);
        ObjectSet("Chart_Sync_ON", OBJPROP_CORNER, CORNER_RIGHT_LOWER);
        ObjectSet("Chart_Sync_ON", OBJPROP_ANCHOR, ANCHOR_RIGHT_LOWER);
        ObjectSet("Chart_Sync_ON", OBJPROP_XDISTANCE, 10);
        ObjectSet("Chart_Sync_ON", OBJPROP_YDISTANCE, 10);
        ObjectSet("Chart_Sync_ON", OBJPROP_BACK, true);
        ObjectSetText("Chart_Sync_ON", CharToString(243), Master_Size, "Wingdings", Master_Color);
        
        EventSetTimer(Timer_Seconds);
        
        return(INIT_SUCCEEDED);
}



void OnDeinit(const int reason) {
        EventKillTimer();
        ObjectDelete(0, "Chart_Sync_ON");
        ChartRedraw();
}



int OnCalculate(
                const int rates_total,
                const int prev_calculated,
                const datetime &time[],
                const double &open[],
                const double &high[],
                const double &low[],
                const double &close[],
                const long &TickVolume[],
                const long &volume[],
                const int &Spread[]
) {
        
        return(rates_total);
}



void OnTimer() {
        ChartRedraw();
}



void OnChartEvent(
                        const int Event_ID,                                     // èäåíòèôèêàòîð ñîáûòèÿ  
                        const long& Event_Long,                 // ïàðàìåòð ñîáûòèÿ òèïà long
                        const double& Event_Double,     // ïàðàìåòð ñîáûòèÿ òèïà double
                        const string& Event_String      // ïàðàìåòð ñîáûòèÿ òèïà string
) {
        if(Event_String == "" || Event_String == "0" || Event_String == "1") return;
        
        if(
                (Event_ID == CHARTEVENT_KEYDOWN && Event_Long == 46) // íàæàòèå êíîïêè Delete
                ||
                Event_ID == CHARTEVENT_MOUSE_MOVE // äâèæåíèå ìûøè, âêëþ÷àÿ ïåðåìåùåíèå îïîðíûõ òî÷åê îáúåêòà
                ||
                Event_ID == CHARTEVENT_OBJECT_DRAG // ïåðåìåùåíèå îáúåêòà ìûøüþ
                ||
                Event_ID == CHARTEVENT_OBJECT_DELETE // óäàëåíèå îáúåêòà
                ||
                Event_ID == CHARTEVENT_OBJECT_CHANGE // èçìåíåíèå ñâîéñòâ îáúåêòà
                ||
                Event_ID == CHARTEVENT_OBJECT_CREATE // ñîçäàíèå îáúåêòà
                ||
                Event_ID == CHARTEVENT_CUSTOM + 1 // îáðàáîòêà ñîçäàííîãî îáúåêòà
        ) {
                if(Event_String == "Chart_Sync_ON") return;
                
                long ia_Symbol_Charts[];
                int
                        i_Symbol_Chart = Get_Chart_IDs(ia_Symbol_Charts, _Symbol),
                        i_Level = 0
                ;
                
                if(i_Symbol_Chart < 1) return; // íå ñ ÷åì ñèíõðîíèçèðîâàòü
                
                while(i_Symbol_Chart-- > 0) {
                        switch(Event_ID) {
                                case CHARTEVENT_KEYDOWN:
                                        ChartRedraw();
                                        break;
                                case CHARTEVENT_OBJECT_CREATE:
                                        EventChartCustom(0, 1, Event_Long, Event_Double, Event_String);
                                        break;
                                case CHARTEVENT_OBJECT_CHANGE:
                                        if(
                                                StringFind(Event_String, "Text") < -1
                                                &&
                                                StringFind(Event_String, "Label") < -1
                                        ) if(ObjectFind(ia_Symbol_Charts[i_Symbol_Chart], Event_String) < 0)
                                                ObjectCreate(ia_Symbol_Charts[i_Symbol_Chart], Event_String, ENUM_OBJECT(ObjectGetInteger(0, Event_String, OBJPROP_TYPE)), 0, ObjectGetInteger(0, Event_String, OBJPROP_TIME, 0), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 0), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 1), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 1), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 2), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 2));
                                        Sync_Object(ia_Symbol_Charts[i_Symbol_Chart], Event_String);
                                        break;
                                case CHARTEVENT_OBJECT_DELETE:
                                        ObjectDelete(ia_Symbol_Charts[i_Symbol_Chart], Event_String);
                                        break;
                                case CHARTEVENT_OBJECT_DRAG:
                                        if(ObjectFind(ia_Symbol_Charts[i_Symbol_Chart], Event_String) < 0)
                                                ObjectCreate(ia_Symbol_Charts[i_Symbol_Chart], Event_String, ENUM_OBJECT(ObjectGetInteger(0, Event_String, OBJPROP_TYPE)), 0, ObjectGetInteger(0, Event_String, OBJPROP_TIME, 0), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 0), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 1), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 1), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 2), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 2));
                                        Sync_Object(ia_Symbol_Charts[i_Symbol_Chart], Event_String);
                                        break;
                                case CHARTEVENT_MOUSE_MOVE:
                                        if(ObjectFind(ia_Symbol_Charts[i_Symbol_Chart], Event_String) < 0)
                                                ObjectCreate(ia_Symbol_Charts[i_Symbol_Chart], Event_String, ENUM_OBJECT(ObjectGetInteger(0, Event_String, OBJPROP_TYPE)), 0, ObjectGetInteger(0, Event_String, OBJPROP_TIME, 0), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 0), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 1), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 1), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 2), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 2));
                                        Sync_Object(ia_Symbol_Charts[i_Symbol_Chart], Event_String);
                                        break;
                                case CHARTEVENT_CUSTOM + 1:
                                        if(ObjectFind(ia_Symbol_Charts[i_Symbol_Chart], Event_String) < 0)
                                                ObjectCreate(ia_Symbol_Charts[i_Symbol_Chart], Event_String, ENUM_OBJECT(ObjectGetInteger(0, Event_String, OBJPROP_TYPE)), 0, ObjectGetInteger(0, Event_String, OBJPROP_TIME, 0), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 0), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 1), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 1), ObjectGetInteger(0, Event_String, OBJPROP_TIME, 2), ObjectGetDouble(0, Event_String, OBJPROP_PRICE, 2));
                                        Sync_Object(ia_Symbol_Charts[i_Symbol_Chart], Event_String);
                                        break;
                        }
                        
                }
        }
}



int Get_Chart_IDs(long& ia_Symbol_Charts[], string s_Symbol) {
        // Ñîáèðàåò â ìàññèâ ia_Symbol_Charts ñïèñîê ID îêîí ñèìâîëà s_Symbol, èñêëþ÷àÿ òåêóùèé
        // Âîçâðàùàåò êîë-âî îêîí ñèìâîëà
        ArrayResize(ia_Symbol_Charts, 0);
        int
                i_Symbol_Chart = 0
        ;
        long
                i_Counter = 0,
                i_This_Chart_ID = ChartID(),
                i_Chart_ID = ChartFirst()
        ;
        while(i_Counter++ < 100) {
                if(i_Chart_ID != i_This_Chart_ID)
                        if(ChartSymbol(i_Chart_ID) == s_Symbol) {
                        ArrayResize(ia_Symbol_Charts, ++i_Symbol_Chart);
                        ia_Symbol_Charts[i_Symbol_Chart - 1] = i_Chart_ID;
                }
                i_Chart_ID = ChartNext(i_Chart_ID);
                if(i_Chart_ID < 0) break;
        }
        
        return(i_Symbol_Chart);
}



void Sync_Object(long i_Chart_ID, string s_Obj_Name) {
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_COLOR, ObjectGetInteger(0, s_Obj_Name, OBJPROP_COLOR));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_STYLE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_STYLE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_WIDTH, ObjectGetInteger(0, s_Obj_Name, OBJPROP_WIDTH));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_BACK, ObjectGetInteger(0, s_Obj_Name, OBJPROP_BACK));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_RAY_LEFT, ObjectGetInteger(0, s_Obj_Name, OBJPROP_RAY_LEFT));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_RAY_RIGHT, ObjectGetInteger(0, s_Obj_Name, OBJPROP_RAY_RIGHT));
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_ANGLE, ObjectGetDouble(0, s_Obj_Name, OBJPROP_ANGLE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_FILL, ObjectGetInteger(0, s_Obj_Name, OBJPROP_FILL));
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_DEVIATION, ObjectGetDouble(0, s_Obj_Name, OBJPROP_DEVIATION));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_ANCHOR, ObjectGetInteger(0, s_Obj_Name, OBJPROP_ANCHOR));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_ARROWCODE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_ARROWCODE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_SELECTABLE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_SELECTABLE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_TIMEFRAMES, ObjectGetInteger(0, s_Obj_Name, OBJPROP_TIMEFRAMES));
        
        ObjectSetString(i_Chart_ID, s_Obj_Name, OBJPROP_TEXT, ObjectGetString(0, s_Obj_Name, OBJPROP_TEXT));
        ObjectSetString(i_Chart_ID, s_Obj_Name, OBJPROP_FONT, ObjectGetString(0, s_Obj_Name, OBJPROP_FONT));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_FONTSIZE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_FONTSIZE));
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_ANGLE, ObjectGetDouble(0, s_Obj_Name, OBJPROP_ANGLE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_XDISTANCE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_XDISTANCE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_YDISTANCE, ObjectGetInteger(0, s_Obj_Name, OBJPROP_YDISTANCE));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_CORNER, ObjectGetInteger(0, s_Obj_Name, OBJPROP_CORNER));
        
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_PRICE, 0, ObjectGetDouble(0, s_Obj_Name, OBJPROP_PRICE, 0));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_TIME, 0, ObjectGetInteger(0, s_Obj_Name, OBJPROP_TIME, 0));
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_PRICE, 1, ObjectGetDouble(0, s_Obj_Name, OBJPROP_PRICE, 1));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_TIME, 1, ObjectGetInteger(0, s_Obj_Name, OBJPROP_TIME, 1));
        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_PRICE, 2, ObjectGetDouble(0, s_Obj_Name, OBJPROP_PRICE, 2));
        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_TIME, 2, ObjectGetInteger(0, s_Obj_Name, OBJPROP_TIME, 2));
        
        int i_Level = int(ObjectGetInteger(0, s_Obj_Name, OBJPROP_LEVELS));
        if(i_Level > 0) {
                ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELS, i_Level);
                while(i_Level-- > 0) {
                        ObjectSetDouble(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELVALUE, i_Level, ObjectGetDouble(0, s_Obj_Name, OBJPROP_LEVELVALUE, i_Level));
                        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELCOLOR, i_Level, ObjectGetInteger(0, s_Obj_Name, OBJPROP_LEVELCOLOR, i_Level));
                        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELSTYLE, i_Level, ObjectGetInteger(0, s_Obj_Name, OBJPROP_LEVELSTYLE, i_Level));
                        ObjectSetInteger(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELWIDTH, i_Level, ObjectGetInteger(0, s_Obj_Name, OBJPROP_LEVELWIDTH, i_Level));
                        ObjectSetString(i_Chart_ID, s_Obj_Name, OBJPROP_LEVELTEXT, i_Level, ObjectGetString(0, s_Obj_Name, OBJPROP_LEVELTEXT, i_Level));
                }
        }
        ChartRedraw(i_Chart_ID);
}

To recreate the error the indicator must be applied to 2 or more charts of the same market (as I need whatever is drawn on any of the charts to appear on the others). The error can be triggered on deletion of an object.

Unfortunately I'm not a programmer. I have paid a programmer in the Freelance section to attempt a fix but after many hours we couldn't find the solution. I have MT4 installed outside of the Programs folder in Windows 7.

If any of you expert programmers have come across this before and know how to solve it I would be most grateful if you could offer some advice or correct the code.

Thank you 

Files:
chart_sync.mq5  10 kb
 

Hi again,

Although no one has responded there has been a little bit of progress with this issue at my end. I'll continue to work on it and provide some expanded information asap - so please don't spend your time on it right now.

Rogh 

 

Well, look with Comment(..) and __LINE__ at the the development of the 'running variable' in your loops:

Comment(__LINE__," loopvar: ",(string)i);
 

stop MT4, ctrl alt suppr

Go to the folder "profil", delete every thing, correct the error, and restart MT4 terminal

 

Ok, just to resolve the issue incase anyone is interested… The problem is that placing Chart_Sync indicator to several charts at once is a type of misuse of the algorithm within that indicator. It seems to work without issues only when placed to one single chart. Otherwise as practice shows it may work incorrectly in combination with several other programs. Generally, to make programs work without conflict with it, whenever some other program makes changes to objects on chart, it should disable chart events, because chain toggling of chart events on several charts in MT4 may results in hanging of terminal. Potentially this can be solved by changing the architecture of Chart_Sync but in this case it’s not worth it for me at least.

 
Rogh:

Ok, just to resolve the issue incase anyone is interested… The problem is that placing Chart_Sync indicator to several charts at once is a type of misuse of the algorithm within that indicator. It seems to work without issues only when placed to one single chart. Otherwise as practice shows it may work incorrectly in combination with several other programs. Generally, to make programs work without conflict with it, whenever some other program makes changes to objects on chart, it should disable chart events, because chain toggling of chart events on several charts in MT4 may results in hanging of terminal. Potentially this can be solved by changing the architecture of Chart_Sync but in this case it’s not worth it for me at least.


You can tell it the Service Desk - but I doubt that you'll get an answer. :(
Reason: