Preguntas de los principiantes MQL5 MT5 MetaTrader 5 - página 1445

 
Evgeny Dyuka #:
Pensé que marcaría una casilla en algún sitio y ya está ))
de todas formas, tendré que aguantarme,
gracias por la respuesta.

¿Escribiste tú mismo ese código? Quizás puedas mostrar un trozo de código de cómo se llama a db y unas líneas después de la llamada. Algo me parece que dice print error.....

 
Alexey Viktorov #:

¿Escribiste tú mismo ese código? Quizás puedas mostrar un trozo de código de cómo se llama a db y unas líneas después de la llamada. Algo me parece que dice para imprimir un error....

La tarea es escribir la hora actual a la base de datos cada 10 segundos. Lo hace el mismo Asesor Experto, pero en 4 gráficos.
Para separarlos por tiempo, he añadido una muletilla en forma de Sleep() tiempo aleatorio - de 0 a 3 segundos.
Y 10 intentos de conexión.
El registro mostró que como máximo en el segundo intento todo funciona, es decir, en general funciona de forma fiable.

.
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
void db_update_lastseen(string symbol)
  {
   string comm = "UPDATE LastSeen SET utime='" +
                 IntegerToString((int)TimeGMT()) +
                 "' WHERE who='mt5' AND symbol='" + symbol + "'";
   if(!db_exe("db_update_lastseen", comm))
      Telegram("⚠MT5 DB ERROR db_update_lastseen() " + symbol, DevChannel);
  }
//+------------------------------------------------------------------+
//|                                                                  |
//+------------------------------------------------------------------+
bool db_exe(string who, string comm, bool readonly = false)
  {
   ResetLastError();
   int count = 0;
   bool repeat = true;
   int dbmt = INVALID_HANDLE;
   while(repeat)
     {
      count++;
      Sleep((int)((float)MathRand() / 10));
      if(count > 10)
        {
         Print("DB: " + who + " failed with code ", GetLastError(), " DatabaseOpen ", " count: ", count);
         return false;
        }
      if(readonly)
         dbmt = DatabaseOpen(path_to_db, DATABASE_OPEN_READONLY);
      else
         dbmt = DatabaseOpen(path_to_db, DATABASE_OPEN_READWRITE);
      if(dbmt == INVALID_HANDLE)
        {
         DatabaseClose(dbmt);
         continue;
        }
      else
        {
         if(!DatabaseExecute(dbmt, comm))
           {
            DatabaseClose(dbmt);
            continue;
           }
         else
           {
            DatabaseClose(dbmt);
            return true;
           }
        }
     }
   DatabaseClose(dbmt);
   return false;
  }
 
Evgeny Dyuka #:
La tarea es escribir la hora actual en la base de datos cada 10 segundos. Lo hace el mismo Asesor Experto, pero en 4 gráficos.
Para separarlos por tiempo añadí una muletilla en forma de Sleep() tiempo aleatorio - de 0 a 3 segundos.
Y 10 intentos de conexión.
El log muestra que como mucho en el segundo intento todo funciona, es decir, en general funciona de forma fiable.

.

Así que aquí está la línea que se imprime en el registro.

         Print("DB: " + who + " failed with code ", GetLastError(), " DatabaseOpen ", " count: ", count);

Basta con comentarla poniendo // delante o quitarla del todo y se eliminarán todas las preguntas si no hay otro Print() en ningún otro sitio;

 
Alexey Viktorov #:

Así que aquí está la línea que imprime a la revista

Basta con comentarla poniendo // delante o borrarla completamente y se eliminarán todas las preguntas, si no hay otro Print() en ningún otro sitio;

Esta línea se imprimirá si falla con 10 intentos.
La propia función imprime el error.


 
Evgeny Dyuka #:

Esta línea se imprimirá si la función falla después de 10 intentos.
El error lo imprime la propia función.


Ya veo. Se imprime cuando se intenta trabajar con db. Necesitamos ver si hay un chequeo de validez del handle de db antes de usar la base de datos.

Aquí has llamado a la función

void db_update_lastseen(string symbol)
  {
   string comm = "UPDATE LastSeen SET utime='" +
                 IntegerToString((int)TimeGMT()) +
                 "' WHERE who='mt5' AND symbol='" + symbol + "'";
   if(!db_exe("db_update_lastseen", comm))
      Telegram("⚠MT5 DB ERROR db_update_lastseen() " + symbol, DevChannel);
  }

Intentaste abrir la db, obtuviste un error, enviaste un mensaje a telegram....

Y donde usas la variable dbmt, ¿compruebas allí su valor?

if(dbmt < 0)
// ничего делать нельзя. База не открыта…

o así

if(dbmt >= 0)
 {
  // Базу можно использовать.
 }
 
Alexey Viktorov #:

Ya veo. Esto se imprime al intentar trabajar con db. Tenemos que ver si hay una comprobación de validez de la manija db antes de utilizar la base de datos.

Aquí has llamado a la función

Intentaste abrir la db, obtuviste un error, enviaste un mensaje a telegram...

¿Y donde usas la variable dbmt compruebas su valor?

o así

Sí, lo compruebo en db_exe() y lo envío a retry. Y db_exe() devolverá False si falla 10 veces (nunca lo ha devuelto).
if(dbmt == INVALID_HANDLE)
        {
         DatabaseClose(dbmt);
         continue;
        }
Creo que la librería de trabajo con la base envía un error y, al parecer, no maneja la situación cuando la base está bloqueada.
En Python tal problema no ocurre, al parecer está incorporado en colas y esperas.

Gracias por sus respuestas.
 
Evgeny Dyuka #:
Sí, lo compruebo en db_exe() y lo envío a reintentar. Pero db_exe() devuelve False si falla 10 veces (nunca devuelve).
Creo que la librería de trabajo con la base manda un error y parece que no maneja la situación cuando la base está bloqueada.
En Python no ocurre tal problema, al parecer tiene colas y esperas.

Gracias por vuestras respuestas.

1. Si no se recupera el handle de la base, no es necesario cerrar la base.

2. Si se recibe INVALID_HANDLE, ¿por qué continuar la ejecución del programa? Creo que en este caso es mejor abortar, devolver

Ahora estoy intentando repetidamente abrir y cerrar una base inexistente y no consigo obtener una impresión de error. Creo que esta impresión se produce en el momento de crear consultas a la base, que no se pudo abrir.

 
Alexey Viktorov #:

1. Si no se recibe el asa de la base, no es necesario cerrar la base.

2. Si se recibe INVALID_HANDLE, ¿por qué continuar la ejecución del programa? Creo que en este caso es mejor interrumpir, devolver

Ahora estoy intentando repetidamente abrir y cerrar una base de datos inexistente y no consigo obtener la impresión de error. Creo que esta impresión se produce en el momento de crear consultas a la base, que no se ha podido abrir.

Voy a hacer una prueba mínima Expert Advisor que actualizará el registro en la base de datos cada segundo. Vamos a ejecutarlo en 10 pares y todo se aclarará. Lo postearé aquí...
 
Evgeny Dyuka #:
Voy a hacer una prueba mínima Asesor Experto que actualizará el registro en la base de datos cada segundo. Ejecutarlo en 10 pares y todo estará claro. Lo publicaré aquí.

Interesante. Estaré esperando...

 
Alexey Viktorov #:

Interesante. Estaré esperando...

Aquí tienes un experto. Crea una base (si no existe ya) y escribe en ella la hora actual una vez por segundo.
No hay Print() en el código.
Lo ejecuté en 10 pares y obtuvo errores:

CS      2       11:44:36.561    Test_DB (EURUSD,M10)    database error, database is locked
CS      2       11:55:27.018    Test_DB (BTCUSD,M10)    database error, database is locked
CS      2       11:55:28.026    Test_DB (BTCUSD,M10)    database error, database is locked
CS      2       11:55:49.177    Test_DB (TRXUSD,M10)    database error, database is locked
CS      2       11:55:51.183    Test_DB (EURUSD,M10)    database error, database is locked
CS      2       11:55:53.182    Test_DB (TRXUSD,M10)    database error, database is locked

Para obtener un error que tiene que cerrar y reiniciar MT5 entonces todos los EAs empezar a trabajar de forma sincrónica.

Sería bueno:
1. Para entender cómo deshacerse de este error.
2. Para inventar un mecanismo de plantilla que la cola en caso de que la base no está disponible.

Resolví el punto 2 añadiendo Sleep() con tiempo aleatorio, pero parece una muletilla.

ACTUALIZACIÓN: Volví a subir el archivo, el primero tenía un error.

Archivos adjuntos:
Test_DB_1.mq5  3 kb
Razón de la queja: