Freezing charts - Error 4203 - page 2

 
Lorentzos Roussos #:

which operations are you performing in your code ?

Maybe a bruteforce test is possible where the code will attempt all possible combinations of adjusting something and then looking for an object .

Also from a "DOM" perspective what Fernando suggested is worth looking into . If something is editing the object it must "render" the object inaccessible for a bit.

Thank you for your effort! I will give it a try. We also wrote some code for indicator and EA same time usage, but could not provoke the freeze by those. 

Regarding what happens in between, please see my answer to Alain. 

 
Doerk Hilger #:

Thank you for your effort! I will give it a try. We also wrote some code for indicator and EA same time usage, but could not provoke the freeze by those. 

Regarding what happens in between, please see my answer to Alain. 

i think i provoked the freeze , did not get a 4203 though .

created an indicator instance of the test.

The test starts on the indicator , as a creator with a 1000 objects.

Look at the refresh rate.

Then start a new chart , place the ea version on it as "editor" , keep adding charts and look at the refresh rate .

Then it will crush .

(so i guess that means there is an "object" protection when its edited and the indicator's thread will stop until the object frees up again)

Indicator version : 

#property version   "1.00"
#property indicator_chart_window
enum _purpose{
creator=0,//create
edit=1//editor
};
input _purpose purpose=creator;//purpose : 
input int objects=1000;//total objects
input double W=100.0;//wiggle points
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
double _point=0.0;
int _digits=0;
long creator_id=-1;
int OnInit()
  {
  creator_id=-1;
  ObjectsDeleteAll(ChartID(),"TEST_");
  EventSetMillisecondTimer(44);
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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 &tick_volume[],
                const long &volume[],
                const int &spread[])
  {
//---
   
//--- return value of prev_calculated for next call
   return(rates_total);
  }
//+------------------------------------------------------------------+
void OnTimer(){

  if(purpose==creator){
    if(creator_id==-1){
    creator_id=ChartID();
    int f=FileOpen("test.txt",FILE_WRITE|FILE_BIN);
    if(f!=INVALID_HANDLE){
    FileWriteLong(f,ChartID());
    FileWriteDouble(f,_Point);
    FileWriteInteger(f,_Digits,INT_VALUE);
    FileClose(f);
    }
    for(int i=0;i<objects;i++){
    ObjectCreate(ChartID(),"TEST_"+IntegerToString(i),OBJ_TREND,0,iTime(_Symbol,_Period,i-20),iHigh(_Symbol,_Period,i-20),iTime(_Symbol,_Period,i),iLow(_Symbol,_Period,i));
    }
    }else{
    int total=ObjectsTotal(creator_id,0);
    ResetLastError();
    uint tickstart=GetTickCount();
    for(int i=0;i<total;i++){
       string name=ObjectName(ChartID(),i,0);
       int e=GetLastError();
       if(e==0){
         //
         if(StringFind(name,"TEST_",0)!=-1){
           double price1=(double)ObjectGetDouble(ChartID(),name,OBJPROP_PRICE,0);
           double price2=(double)ObjectGetDouble(ChartID(),name,OBJPROP_PRICE,1);
           double wiggle=NormalizeDouble((((double)rand())/((double)32767.0)-0.5)*(W*_Point),_Digits);
           price1+=wiggle;
           price2-=wiggle;
           ObjectSetDouble(ChartID(),name,OBJPROP_PRICE,0,price1);
           ObjectSetDouble(ChartID(),name,OBJPROP_PRICE,1,price2);
           }
         //
         }else{
         Print("Error reading object ("+IntegerToString(i)+") #"+IntegerToString(e));
         }
       }
    ChartRedraw(ChartID());
    uint tickend=GetTickCount();
    long delta=tickend-tickstart;
    if(tickend<tickstart){delta=UINT_MAX+tickend-tickstart;}
    Comment("Go through objects delta ("+IntegerToString(delta)+")ms");
    }
  }else{
  if(creator_id==-1){
    int f=FileOpen("test.txt",FILE_READ|FILE_BIN);
    if(f!=INVALID_HANDLE){
    creator_id=(long)FileReadLong(f);
    _point=(double)FileReadDouble(f);
    _digits=(int)FileReadInteger(f,INT_VALUE);
    FileClose(f);
    }
    }else{
    int total=ObjectsTotal(creator_id,0);
    ResetLastError();
    for(int i=0;i<total;i++){
       string name=ObjectName(creator_id,i,0);
       int e=GetLastError();
       if(e==0){
         //
         if(StringFind(name,"TEST_",0)!=-1){
           double price1=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,0);
           double price2=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,1);
           double wiggle=NormalizeDouble((((double)rand())/((double)32767.0)-0.5)*(W*_point),_digits);
           price1+=wiggle;
           price2-=wiggle;
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,0,price1);
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,1,price2);
           }
         //
         }else{
         Print("Error reading object ("+IntegerToString(i)+") #"+IntegerToString(e));
         }
       }
       ChartRedraw(creator_id);
    }
     
  }
}

void OnDeinit(const int reason)
  {
  ObjectsDeleteAll(ChartID(),"TEST_");
  }

EA Version : 

#property version   "1.00"
enum _purpose{
creator=0,//create
edit=1//editor
};
input _purpose purpose=creator;//purpose : 
input int objects=1000;//total objects
input double W=100.0;//wiggle points

double _point=0.0;
int _digits=0;
long creator_id=-1;
int OnInit()
  {
  creator_id=-1;
  ObjectsDeleteAll(ChartID(),"TEST_");
  EventSetMillisecondTimer(44);
  return(INIT_SUCCEEDED);
  }

void OnTimer(){

  if(purpose==creator){
    if(creator_id==-1){
    creator_id=ChartID();
    int f=FileOpen("test.txt",FILE_WRITE|FILE_BIN);
    if(f!=INVALID_HANDLE){
    FileWriteLong(f,ChartID());
    FileWriteDouble(f,_Point);
    FileWriteInteger(f,_Digits,INT_VALUE);
    FileClose(f);
    }
    for(int i=0;i<objects;i++){
    ObjectCreate(ChartID(),"TEST_"+IntegerToString(i),OBJ_TREND,0,iTime(_Symbol,_Period,i-20),iHigh(_Symbol,_Period,i-20),iTime(_Symbol,_Period,i),iLow(_Symbol,_Period,i));
    }
    }else{
    int total=ObjectsTotal(ChartID(),0);
    ResetLastError();
    uint tickstart=GetTickCount();
    for(int i=0;i<total;i++){
       string name=ObjectName(ChartID(),i,0);
       int e=GetLastError();
       if(e==0){
         //
         if(StringFind(name,"TEST_",0)!=-1){
           double price1=(double)ObjectGetDouble(ChartID(),name,OBJPROP_PRICE,0);
           double price2=(double)ObjectGetDouble(ChartID(),name,OBJPROP_PRICE,1);
           double wiggle=NormalizeDouble((((double)rand())/((double)32767.0)-0.5)*(W*_Point),_Digits);
           price1+=wiggle;
           price2-=wiggle;
           ObjectSetDouble(ChartID(),name,OBJPROP_PRICE,0,price1);
           ObjectSetDouble(ChartID(),name,OBJPROP_PRICE,1,price2);
           }
         //
         }else{
         Print("Error reading object ("+IntegerToString(i)+") #"+IntegerToString(e));
         }
       }
    ChartRedraw(ChartID());
    uint tickend=GetTickCount();
    long delta=tickend-tickstart;
    if(tickend<tickstart){delta=UINT_MAX+tickend-tickstart;}
    Comment("Go through objects delta ("+IntegerToString(delta)+")ms");
    }
  }else{
  if(creator_id==-1){
    int f=FileOpen("test.txt",FILE_READ|FILE_BIN);
    if(f!=INVALID_HANDLE){
    creator_id=(long)FileReadLong(f);
    _point=(double)FileReadDouble(f);
    _digits=(int)FileReadInteger(f,INT_VALUE);
    FileClose(f);
    }
    }else{
    int total=ObjectsTotal(creator_id,0);
    ResetLastError();
    for(int i=0;i<total;i++){
       string name=ObjectName(creator_id,i,0);
       int e=GetLastError();
       if(e==0){
         //
         if(StringFind(name,"TEST_",0)!=-1){
           double price1=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,0);
           double price2=(double)ObjectGetDouble(creator_id,name,OBJPROP_PRICE,1);
           double wiggle=NormalizeDouble((((double)rand())/((double)32767.0)-0.5)*(W*_point),_digits);
           price1+=wiggle;
           price2-=wiggle;
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,0,price1);
           ObjectSetDouble(creator_id,name,OBJPROP_PRICE,1,price2);
           }
         //
         }else{
         Print("Error reading object ("+IntegerToString(i)+") #"+IntegerToString(e));
         }
       }
       ChartRedraw(creator_id);
    }
     
  }
}

void OnDeinit(const int reason)
  {
  ObjectsDeleteAll(ChartID(),"TEST_");
  }

void OnTick()
  {

  }

void OnChartEvent(const int id,const long& lparam,const double& dparam,const string& sparam)
  {

  }
 
Lorentzos Roussos #:

i think i provoked the freeze , did not get a 4203 though .

created an indicator instance of the test.

The test starts on the indicator , as a creator with a 1000 objects.

Look at the refresh rate.

Then start a new chart , place the ea version on it as "editor" , keep adding charts and look at the refresh rate .

Then it will crush .

(so i guess that means there is an "object" protection when its edited and the indicator's thread will stop until the object frees up again)

Indicator version : 

EA Version : 

Wow. You´re great. Thank you. 

We will clearly check/use/test this. 

The questions which come up are: Why was this never a problem with older versions and is there a way to avoid it? We already thought about to do all the objects stuff only in the EA by using a pipe, but this means loads of effort until this is implemented. The chart metrics stuff works already like this, since this was a massive problem a year ago - also just nowadays. 

Nonetheless, this behavior is clearly not meant to be like this. I mean, there are chartevens occuring in the EA when the indicator creates objects, but if it can´t access it without problems and without freezes, then its totally senseless. 

In earlier versions of my EA I even used chart objects (text) to transmit data between indicators and the EA, and they were accessed on tick-basis. For years - no problems at all - never. I have no clue what MQ sometimes has in mind with their "improvements", but the more they "improve", the worse it gets. Since years also we are mainly busy with finding workarounds coz they simply don´t care about misbehavior of MetaTrader with their new "features". This is getting more and more dangerous for our business. And even simple bugs, which are easy to reproduce, they don´t fix them. Just not. 

 

Interesting thing:

I debugged again the problem, where this time the function "::ObjectFind(chartid,name);" is the brake. I searched the object with the given name manually in the chart, and see the following:

 

The object is a line object, and the value is clearly not zero (0). 

When I check objects in the list which come AFTER this object, they all show the same data: Black (0), Value 0. These objects were created by the indicator in the same chart, and its clearly not blocking all the objects same time. The objects in the list BEFORE this object all show valid data. 

All in all, the chart shows 3.135 objects, which is also not correct, it should be not more than 1.500. It seems like, that there are plenty of orphan objects, which obviously could not be deleted for whatever reason. 

This is clearly a topic for MetaQuotes. 

 
Doerk Hilger #:

Wow. You´re great. Thank you. 

We will clearly check/use/test this. 

The questions which come up are: Why was this never a problem with older versions and is there a way to avoid it? We already thought about to do all the objects stuff only in the EA by using a pipe, but this means loads of effort until this is implemented. The chart metrics stuff works already like this, since this was a massive problem a year ago - also just nowadays. 

Nonetheless, this behavior is clearly not meant to be like this. I mean, there are chartevens occuring in the EA when the indicator creates objects, but if it can´t access it without problems and without freezes, then its totally senseless. 

In earlier versions of my EA I even used chart objects (text) to transmit data between indicators and the EA, and they were accessed on tick-basis. For years - no problems at all - never. I have no clue what MQ sometimes has in mind with their "improvements", but the more they "improve", the worse it gets. Since years also we are mainly busy with finding workarounds coz they simply don´t care about misbehavior of MetaTrader with their new "features". This is getting more and more dangerous for our business. And even simple bugs, which are easy to reproduce, they don´t fix them. Just not. 

maybe it was a problem and you never used this many objects 

Why do you need to read all these lines if i may ask ?(and constantly since you mentioned "crashes after hours")

 

My assumption is simply:

All the chart objects are stored in an MMF, since this is kinda the only chance to access the same memory from different threads. 

The prior post shows that the chart itself is not frozen, since it interacts with mouse clicks, but the data is not accessible. In case another thread accessed the data (Windows view function), in this case the indicator, there must be a missing unlock (Windows unview) of the MMF and the thread of the EA constantly gets timeouts. Same as the manual obtaining of the data by checking the objects list of the chart manually, it cannot access the data of the objects - coz the MMF is still locked/viewed by mistake. 

Anything else makes no sense, and there is even no chance to reactivate the chart, since the viewing process has to unview the data. I just can close it. 

Does anyone here has the chance to involve the support of MetaQuotes? Imho this is totally obvious that this leads to the direction of the bug.  

 
Lorentzos Roussos #:

maybe it was a problem and you never used this many objects 

Why do you need to read all these lines if i may ask ?(and constantly since you mentioned "crashes after hours")

This indicator is used for sharing setups. It updates lines etc. by itself, enhances rectangles related to gaps etc. and uploads the data after something changed, so that subscribers have the updated data in realtime in their charts. This happens overnight as well. 

Before this issue came up, it was more than 30.000 objects. I cleared the charts, since I thought that might be the problem, and now its less than 1.000. 

 
Doerk Hilger #:

This indicator is used for sharing setups. It updates lines etc. by itself, enhances rectangles related to gaps etc. and uploads the data after something changed, so that subscribers have the updated data in realtime in their charts. This happens overnight as well. 

Before this issue came up, it was more than 30.000 objects. I cleared the charts, since I thought that might be the problem, and now its less than 1.000. 

Out of curiosity , can't you render the levels internally and send them ? I mean you are "receiving" the level anyway from what i understand , then drawing it .

its an api or smth? 

 
Lorentzos Roussos #:

Out of curiosity , can't you render the levels internally and send them ? I mean you are "receiving" the level anyway from what i understand , then drawing it .

its an api or smth? 

Sure I can find workarounds for this indicator, like I mentioned: I tell the EA to create the objects, since they are stored in a file anyway. But its is not the only one which comes up with this issue recently, its just the worst of them all, since it manages the most chart objects. And on top: We still have no clue when this issue comes up, and I need a general solution for all the stuff. 

 
Doerk Hilger #:

Sure I can find workarounds for this indicator, like I mentioned: I tell the EA to create the objects, since they are stored in a file anyway. But its is not the only one which comes up with this issue recently, its just the worst of them all, since it manages the most chart objects. And on top: We still have no clue when this issue comes up, and I need a general solution for all the stuff. 

i see . If its all custom objects why use an indicator though ?

Reason: