Errori, bug, domande - pagina 2540

 
Сергей Таболин:

Che cosa vuoi?

In modo che persone incompetenti come te, Fedoseyev, ecc. non entrino con i loro commenti nella discussione di bug e disegni.

Che le costruzioni e i meccanismi presi in MQL dal C++ nella loro interezza e che sembrano uguali a quelli del C++ funzionano come in C++.

Sergei Tabolin:

Perché MQL sia un analogo completo del C++?

È una stronzata e tu lo sai, ma devi buttarla lì.
Sergey Tabolin:

E smettila di lamentarti e di soffiare bolle di moccio per questo. Ho aperto un thread separato per queste "discussioni".

Sei tu quello che si lamenta di quanto sia fastidioso, di una lingua separata e di un thread separato.

Apri un thread separato per te e i tuoi simpatizzanti e lamentati lì.

 
Come fare in modo che il terminale rilasci il file mqd? O ancora meglio, se ci fosse un modo interno per cancellarlo dall'interfaccia?
 
Stanislav Korotky:
Come fare in modo che il terminale rilasci il file mqd? O ancora meglio, se ci fosse un modo interno per rimuoverlo dall'interfaccia?

Posso indovinare approssimativamente di cosa tratta la domanda. Meglio riaffermarlo.

 
Penso che ci sia un problema con la deinizializzazione della dll nei servizi, aiutatemi a capire.
Il problema è questo. Dopo aver premuto il comando "Stop" nel menu Service, il terminale non aspetta che la funzione Fn() finisca per qualche motivo.
Tenta prematuramente di interrompere la connessione con la dll, riagganciando il terminale o si blocca completamente (si chiude).
Anche se al punto d'ingresso DllMain, il flag Detach in DLL_PROCESS_DETACH imposta esplicitamente un flag per terminare il ciclo while.

Ma while non ha il tempo di uscire dal ciclo in tempo per eseguire le funzioni sottostanti, dopo che tutti gli altri processi hanno completato ulteriormente.
E terminare la funzione Fn() stessa.
La funzione DestroyFunction(); funge da controllo in questo esempio.

Il contenuto del dll

#define  EXP extern "C" __declspec(dllexport)

void DestroyFunction(void);
EXP void __stdcall Fn(int num);

bool Detach;

//---------------------------------------------------------------------
BOOL APIENTRY DllMain(HMODULE hModule, DWORD  ul_reason_for_call, LPVOID lpReserved)
{
        switch (ul_reason_for_call)
        {
                case DLL_PROCESS_ATTACH:
                        Detach = false;
                        break;
                case DLL_THREAD_ATTACH:
                        break;
                case DLL_THREAD_DETACH:
                        break;
                case DLL_PROCESS_DETACH:
                        Detach = true;
                        break;
        }
        return TRUE;
}

//---------------------------------------------------------------------
void DestroyFunction()
{
        MessageBoxW(NULL, L"Start DestroyFunction", L"OK", MB_OK);

        return;
}

//---------------------------------------------------------------------
EXP void __stdcall Fn(int num)
{
        int count = num;

        while (Detach == false)
        {
            //Имитация работы цикла
            count++;    

            if (count > 0)
                MessageBoxW(NULL, L"Start While iteration", L"OK", MB_OK);

            Sleep(10000);
        }       

 
        //После нажатия команды "Остановить" в меню Сервис, сюда уже не доходим, так как уже висим, или вылетел терминал.
        DestroyFunction();

        
        return;
}


Il contenuto del programma Service.
Il ritardo aggiuntivo di _StopFlag non aiuta.

//+------------------------------------------------------------------+
//|                                                      BugDll.mq5 |
//|                        Copyright 2019, MetaQuotes Software Corp. |
//|                                             https://www.mql5.com |
//+------------------------------------------------------------------+
#property service
#property copyright "Copyright 2019, MetaQuotes Software Corp."
#property link      "https://www.mql5.com"
#property version   "1.00"
#property strict
#property script_show_inputs


#import "BugDll.dll"
   void Fn(int num);
#import


//+------------------------------------------------------------------+
//| Service program start function                                   |
//+------------------------------------------------------------------+
int OnStart()
{      
   
   Fn(0);

   if(_StopFlag)
      Sleep(10000);
   
   return(0);
}
//+------------------------------------------------------------------+
File:
MQL5.zip  54 kb
 
Roman:
Penso che ci sia un problema con la deinizializzazione della dll in Services, aiutatemi.

la dll non è (necessariamente) scaricata immediatamente dopo la fine del servizio (potrei sbagliarmi)

In ogni caso, quello che fate con DLL_PROCESS_DETACH è troppo tardi. Fate una funzione esplicita di deinit in dll che imposti questa bandiera e chiamatela esplicitamente quando il servizio finisce.

 
Roman:

Il terminale inizierà a scaricare la lib dopo che il thread ritorna da start(), credo. Altrimenti, come funziona? Il programma è in esecuzione e inizia a rompere il suo ambiente? Questa è una sciocchezza. Avviate un thread separato nella lib, non inseguendo un thread di script in un ciclo, e sarà in grado di terminare normalmente.

 
Vict:

Il terminale inizierà a scaricare la lib dopo che il thread ritorna da start(), credo. Altrimenti come funziona? Il programma è in esecuzione e inizia a rompere il suo ambiente? Questa è una sciocchezza. Avviare un thread separato nella lib, e sarà in grado di terminare normalmente.

Il fatto è che ho lo stesso problema con i thread, e a causa di questo non posso terminare correttamente altri processi (thread), che hanno un mucchio di oggetti che devono essere distrutti.
Non riesco a terminare correttamente gli altri processi (cioè non posso uccidere altri processi).
Il terminale funziona in modo errato con il punto di uscitaDLL_PROCESS_DETACH.

Proverò quello che ha suggerito TheXpert, ma il fatto che il terminale scarica la dll immediatamente, indipendentemente da DLL_PROCESS_DETACH, deve essere un errore del terminale.

TheXpert:

La dll non è (necessariamente) scaricata immediatamente dopo la fine del servizio (potrei sbagliarmi)

Comunque, quello che state facendo con DLL_PROCESS_DETACH è troppo tardi. Fare una funzione esplicita deinit in dll, che imposti questa bandiera e la chiami esplicitamente allo spegnimento del servizio.

Grazie per il suggerimento, proverò così.

 
Roman:

Il fatto è che ho lo stesso problema con i thread e a causa di questo, non posso terminare correttamente altri processi (thread) che hanno un mucchio di oggetti che devono essere distrutti.
Non riesco a terminare correttamente gli altri processi (cioè non posso farci niente).
Il terminale funziona in modo errato con il punto di uscita DLL_PROCESS_DETACH.

Proverò quello che ha suggerito TheXpert, ma il terminale scarica la dll in una volta sola, indipendentemente da DLL_PROCESS_DETACH, deve essere un bug del terminale.

Grazie per il suggerimento, proverò in questo modo.

Cosa ti fa pensare che il dll viva in un thread separato? Avete un banale crash di programma che non viene gestito nelle condizioni di loop.

E DllMain viene eseguito quando si connette/disconnette la dll al processo DLL_PROCESS e quando crea/termina il thread creato in questo processo DLL_THREAD. Così il vostro bool Detach, non esiste necessariamente all'interno della dll, perché il compilatore può averlo rimosso nel quadro dell'ottimizzazione, perché durante l'esecuzione di tutte le funzioni durante la vita della dll non cambia ed è uguale a false.

 
Vladimir Simakov:

Cosa ti fa pensare che il dll viva in un thread separato? Avete un banale crash di programma che non viene gestito nelle condizioni di loop.

E DllMain viene avviato quando si collega/disconnette la dll al processo DLL_PROCESS e quando si crea/disconnette un thread, creato in questo processo DLL_THREAD. Così il vostro bool Detach, non esiste necessariamente all'interno della dll, perché il compilatore può averlo rimosso nel quadro dell'ottimizzazione, perché durante l'esecuzione di tutte le funzioni durante la vita della dll non cambia ed è uguale a false.

Non è stato detto da nessuna parte che il dll vive in un thread separato.
Noi comunichiamo con Vict e ci capiamo )).
Capisco che è un crash, non capisco perché il flag in DLL_PROCESS_DETACH non funziona per uscire dal ciclo while.
Per quanto riguarda DLL_THREAD, non sono affatto disponibili per mql, è scritto in questo articolo, ho controllato e davvero non funzionano.
Ma con il compilatore VS come opzione, potrebbe anche essere un trucco.
Mi piacerebbe sentire spiegazioni da rappresentanti competenti piuttosto che tirare a indovinare ))

 
Roman:
Penso che ci sia un problema con la deinizializzazione della dll nei servizi, aiutatemi a capire.
Il problema è questo. Dopo aver premuto il comando "Stop" nel menu Service, il terminale non aspetta che la funzione Fn() finisca per qualche motivo.
Tenta prematuramente di interrompere la connessione con la dll, sospendendo il terminale o si blocca completamente (si chiude).
Anche se al punto d'ingresso DllMain, il flag Detach in DLL_PROCESS_DETACH imposta chiaramente un flag per terminare il ciclo while.

Ma while non ha il tempo di uscire dal ciclo in tempo per eseguire le funzioni sottostanti, dopo che tutti gli altri processi hanno completato ulteriormente.
E terminare la funzione Fn() stessa.
La funzione DestroyFunction(); funge da controllo in questo esempio.

Il contenuto del dll


Il contenuto del programma Service.
Il ritardo aggiuntivo di _StopFlag non aiuta.


Quindi non hai ripreso il controllo del terminale, ti sei "bloccato" in un ciclo "infinito" all'interno del Fn nella DLL.
Di che tipo di licenziamento normale stiamo parlando!

Se avete bisogno di tale comportamento, allora all'interno di Fn in DLL dovreste eseguire un thread separato con un ciclo, che dovrebbe essere fermato da un flag, che è impostato nella funzione separata FnStop e in DLL_PROCESS_DETACH