Intercambio de datos entre dos EAs que se ejecutan en diferentes terminales - página 3

 

Еще можно попробовать забить гвоздь лампочкой. У некоторых получается.

¿Qué hay de malo en este enfoque?

También puede ajustar la hora del sistema.

Así se sincroniza la hora del sistema :-). No a través de la ambientación, sino de la lectura. Se trata de un tipo de intercambio de datos.

 




Buenos días a todos!

Una de las mejores formas de conectar terminales de forma fiable parece ser el uso de la red 1C.
Dos características principales:
1. La aplicación principal se ejecuta en 1C, los terminales y sus programas MQL4 son los ejecutores,
2. La aplicación principal se ejecuta en uno de los terminales, la aplicación 1C se utiliza como protocolo de enlace.

Ventajas:
1. La capacidad de almacenar y procesar el historial completo de cotizaciones simultáneamente en diferentes servidores;
2

 
Andres >> :

Ya he escrito una pequeña biblioteca y mis Asesores Expertos ya están cambiando la información a través del registro. De hecho, se cambian a través del registro, no veo ninguna operación de lectura-escritura en el disco.


Gracias por facilitar la biblioteca. También me ocuparé de la aplicación de este intercambio.

Hay una pregunta obvia de inmediato. ¿Cómo ha implementado la comprobación de parámetros de lectura/escritura? Es decir, ¿cómo sabe otro EA que un determinado parámetro de una clave ya puede ser leído?

¿Crean alguna clave de permiso de lectura/escritura adicional por otro EA o hay alguna otra característica que hayan probado? Es decir, en otras palabras, ¿cómo proporcionar un acceso unitario a un parámetro para que los EAs no trabajen con el mismo parámetro clave al mismo tiempo para evitar fallos?

 

Ya me he dado cuenta de cómo proporcionar un acceso unitario al parámetro clave. Simplemente se comprueba si hay errores utilizando la función GetErrorString( int ErrorCode).

Y en caso de error hay que repetir la operación. Pero no he entendido en qué parte de la biblioteca se realiza esta operación repetida. Tal vez tenga que añadir algo que sea necesario para mí. De todos modos, ¡gracias por la buena solución!

 

Se trata de una simple envoltura sobre la API de Win, con salida de error que sólo permite trabajar con parámetros de clave de cadena.

GetErrorString( int ErrorCode ) es más bien indicativo, para que cuando se produzcan errores, sepa qué, dónde, por qué y cómo solucionarlo. Por supuesto, podemos y debemos poner el manejo de los errores más allá de los límites de las funciones de envoltura y de la biblioteca, y reaccionar ante ellos de diferentes maneras (hay muchos tipos de errores), basándonos en la lógica de uso de las claves por parte de varios expertos. Mientras tanto, SetStringValue() en cualquier intento fallido sólo puede decirle que el intento falló. Y GetStringValue(), en caso de fallo, no sólo se lo dirá, sino que devolverá una cadena vacía. Creo que no hay necesidad de una clave de permiso de lectura/escritura adicional, porque esas comprobaciones las hace el SO. El tratamiento de los errores y la respuesta adecuada a los mismos es suficiente. Mis EAs para la prueba "en caliente" están simplemente desincronizados en el tiempo, probablemente por eso no tenían conflictos al leer/escribir un campo al mismo tiempo. Pero esto no es una solución, por supuesto. Tenemos que seguir adelante. Aun así lo escribí durante una noche, no lo juzgues con demasiada severidad. Una especie de versión "betta", para sentir el método :-).

 
Andres >> :

Ya he escrito una pequeña biblioteca, y mis EAs ya están cambiando la información a través del registro. De hecho, se cambian a través de la RAM, sin lectura-escritura en el disco no observo. En MSDN está escrito que es mejor no meter datos de más de un par de cientos de Kb en el registro.

La biblioteca está configurada de tal manera que todas las claves y parámetros se crean en el área temporal del registro y no se escriben en el registro permanente. Después de reiniciar, estas teclas han desaparecido.

Un PERO, la librería sólo funciona con parámetros de cadena, de no más de 255 caracteres (limitación en MQL). Pero esto es suficiente. En general los parámetros en el registro pueden ser de diferentes tipos, no sólo cadenas, pero por ahora otros tipos no son necesarios en mi opinión. Ahora mismo tengo dos EAs intercambiados a través del registro, pero puede que sean necesarios más :-). Otra cosa buena es que en Win API es posible conectarse al registro de la red. Si alguien necesita intercambiar información entre EAs que se ejecutan en diferentes ordenadores de la misma red, puede buscar en esta dirección. En mi opinión, es rápido, sencillo y fiable, y sin dlls ni archivos. Entrada de una cadena, salida de una cadena.

Andrey, ¡gracias!

Lo he editado y recortado ligeramente.

¿Quizás deberías poner esto en tu hucha? Una solución digna, sin duda.

Archivos adjuntos:
reglib.rar  11 kb
 

Un día de estos integraré tu biblioteca, Andrey, con mi biblioteca para manejar variables gráficas. Me dará un nivel más de declaración de variables.

1. Habrá una GlobalSuperVariable. Dicha variable será visible a nivel del sistema operativo.

2. Ahora existe GlobalVariable.

3. También existe GlobalChartVariable. Sólo son visibles para una ventana.

En general, debe producir una biblioteca para trabajar con sus estructuras a nivel del sistema operativo en MQL4.

 
Zhunko >> :

1. Habrá una GlobalSuperVariable. Dicha variable será visible a nivel del sistema operativo.

Estaré muy agradecido (y probablemente no sea el único) si subes dicha variable a la kodobase.

Cansado de inventarlo con métodos caseros.

 

Pregunta para Andrew. ¿Se mantendrá este registro?

string GetStringValue1 (int    hKey,      // Код ключа реестра.
                        int    lpSize,    // Длина считываемой строки.
                        string ValueName) // Имя параметра ключа.
 {
  int lpType[1];      // Возвращаемый тип параметра.
  int lpcbData[1];    // Размер буфера.
  int i;              // Переменная для подрезки последних пустых строк.
  int lres;           // Результат.
  string lpData = ""; // Буфер для возвращаемой строки.
  //----
  lpcbData[0] = lpSize; // Размер буфера.
  for ( i = 0; i < lpSize; i++) lpData = lpData + "#";
  lres = RegQueryValueExA ( hKey, ValueName, 0, lpType, lpData, lpcbData); // вызов API
  // Теперь в lpcbData[0] размер скопированных байт. Проверяем результат.
  if ( lres != ERROR_SUCCESS)
   {
    Print ("Error in RegQueryValueExA(): ", GetErrorString ( lres));
    return ("");
   }
  if ( lpType[0] == REG_SZ || lpType[0] == REG_EXPAND_SZ) return (StringSubstr ( lpData, 0, lpcbData[0] - 1));
  return ("");
 }
 
Te lo explicaré. La cuestión es que si se utiliza una cadena que se incrementa dinámicamente como buffer, habrá algunos errores. Yo mismo he tropezado con uno antes:
InitRegDefines();
hKey = CreateKey( HKEY_CURRENT_USER, "!MT4TestKey" );

// заносим
SetStringValue( hKey, "Param", "Test" );

// вытаскиваем при помощи Вашей функции:
Print( GetStringValue1( hKey, 20, "Param" ) );

Después de eso resulta:

2009.05.19 01:22:16 2008.12.31 01:49 temp EURUSD,M1: ####
2009.05.19 01:22:16 2008.12.31 01:49 temp EURUSD,M1: RegCreateKeyExA(): Se ha creado una partición inexistente.
2009.05.19 01:22:16 temp comenzó para las pruebas

Es decir, el contenido del buffer no cambia, aunque no hay errores cuando se llama. Y es la línea de "Prueba" en el registro.

He aprendido de los mensajes del foro que sucede debido a alguna cadena extraña que pasa del entorno MQL a las funciones DLL. En el entorno MQL los desarrolladores operan con cadenas utilizando su propio gestor (pool de cadenas), y aparentemente en este borde se llena el buffer equivocado y por lo tanto no podemos ver el resultado devuelto por la función API. Pero si usamos cadenas inicializadas a toda la longitud máxima, entonces, por lo que veo, no hay problema. Por eso está la cadena de 255 caracteres "#". El carácter "#" se ha elegido simplemente para que la cadena sea visible a simple vista. No tiene nada que ver con la propia API de Win, porque no importa con qué se llena el búfer antes de la llamada. Esta es la limitación de la longitud de la cadena que mencioné antes. Puede pasar cadenas de más de 255 caracteres a SetStringValue(), pero no es posible leerlas.

Por supuesto que es bueno no tener limitaciones, pero no veo que sea un gran inconveniente. Esto nos lleva a preguntarnos: ¿por qué hay que leer una cadena de un tamaño determinado? Si se trata de restricciones, puede evitarlas escribiendo una función que divida la cadena de entrada en N parámetros de 255 de longitud + el parámetro "resto". Y al leerlo lo recoge de nuevo. No hay otra manera. Si tiene dificultades, póngase en contacto conmigo, lo haré. Sólo las necesidades de cada uno son diferentes, no se puede proporcionar todo, es suficiente para mí sólo esto, y alguien utiliza las variables globales, e incluso en varios niveles.

Razón de la queja: