DLL error in while() loop

 

Hi!

I have a DLL called from an EA which works fine as long as the EA's start() is called on incoming ticks only.

Now I changed the EA so that the whole logic runs in a while() loop within start() which executes every 200 msecs. Since this change the DLL works the first time I call it but aborts with the following error the second time it is called:

" function xxx call from dll xxx critical error"

Any idea what could be wrong?

Thanks!

 
Source code:


int IntervallMSecs = 200;

int start()
{
   while(!IsStopped())
   {
      // call DLL
      if (some conditions) CallDLL;
      
      // if enabled sleep shortly
      if (IntervallMSecs > 0)
      {
         Sleep(IntervallMSecs);
         RefreshRates();
      }
      else
         break;
   }
   return(0);
}
 
DH008:

Any idea what could be wrong?

No, but a couple of thoughts.

1) You could increase the delay time and see if the errors stop.

2) You could loop on the RefreshRates() call until the price changes.

It is not clear why you would need to re-call the DLL if the rates have not changed (unless this is a multi-currency thing and the rates can update on another pair).

 
DH008:

Any idea what could be wrong?

If it works when called per tick, but not in an infinite loop, then you probably have the opposite of a common problem.

If you are calling the DLL from an infinite loop, then each call will be on the same thread. If you call the DLL per tick, then each call will be from a separate thread, because MT4 creates a new, disposable thread to handle each EA tick. It's fairly common for DLLs to have problems because they contain an assumption that they will always be called from a single persistent thread. You appear to have the opposite of such a problem.

But it's impossible to say what without seeing the DLL code. (Posting the MQ4 code isn't any help.)
 
jjc:
If it works when called per tick, but not in an infinite loop, then you probably have the opposite of a common problem. [...]
...Or, if you are running more than one copy of the EA at once, then you may have a very common problem. Calling the DLL at 200ms intervals rather than on each tick will substantially increase the likelihood that multiple copies of the EA make simultaneous calls to the DLL. If the EA works when there's only one copy of it running, but starts failing when there are multiple copies, then you have a re-entrancy problem in the DLL.
 

Thanks for all the response!

@dabbler: The EA should respond to objects moved on the chart, independent of incoming ticks.

@jjc:

"It's fairly common for DLLs to have problems because they contain an assumption that they will always be called from a single persistent thread. You appear to have the opposite of such a problem. "

That's what I think too. Do you have an idea how to fix it?

Enclosed code of the DLL:

Thanks, DH

#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <stdlib.h>
#include <stdio.h>

#include "Form1.h"

#define MT4_EXPFUNC __declspec(dllexport)

#pragma unmanaged

BOOL APIENTRY DllMain(HANDLE hModule,DWORD ul_reason_for_call,LPVOID lpReserved)
  {
   switch(ul_reason_for_call)
     {
      case DLL_PROCESS_ATTACH:
      case DLL_THREAD_ATTACH:
      case DLL_THREAD_DETACH:
      case DLL_PROCESS_DETACH:
         break;
     }
   return(TRUE);
  }

#pragma managed

MT4_EXPFUNC bool __stdcall GetState(const int icmd, double *ddata, int *idata, const int idigits)
  {
         using namespace System;
         using namespace System::Windows::Forms;
         Application::EnableVisualStyles();
         Application::SetCompatibleTextRenderingDefault(false); 
        
         using namespace FormTest;

         p_cmd                  = icmd;
         p_lots                 = ddata[0];
         p_entry                = ddata[1];
         p_sl                   = ddata[2];
         p_tp                   = ddata[3];
         p_increment            = idata[0];
         p_digits               = idigits;

         Application::Run(gcnew Form1());
   
         ddata[0] = p_lots;
         ddata[1] = p_entry;
         ddata[2] = p_sl;
         ddata[3] = p_tp;
         idata[0] = p_increment;

         return(true);
  }
 
DH008:

Enclosed code of the DLL: [...]

I'm not very familiar with using CLR artifacts from C++, but there's a number of similar things which could be happening here. SetCompatibleTextRenderingDefault() is only meant to be called once per application. It's possible that you can get away with calling it once per thread, but that it starts causing problems when called multiple times on the same thread. For example, your critical error might be a CLR exception which isn't getting trapped. Similarly, Application::Run() is going to create a message pump on the current thread. If you attempt to create a second pump on the same thread then it's again possible that you're getting an untrapped CLR exception which manifests as a critical error.

By the way, bool is different to BOOL, and you really ought to use the latter when passing data to and from MT4.
 
jjc:
I'm not very familiar with using CLR artifacts from C++, but there's a number of similar things which could be happening here. SetCompatibleTextRenderingDefault() is only meant to be called once per application. ...

I'm as well not familiar with using CLR from C++. But your train of thought was right, calling SetCompatibleTextRenderingDefault() and EnableVisualStyles() just once did the trick!

Thanks, DH

         using namespace System;
         using namespace System::Windows::Forms;

         // init Chart-Trader dialog once

         static bool InitDone = false;
         if (!InitDone)
         {
                Application::EnableVisualStyles();
                Application::SetCompatibleTextRenderingDefault(false); 
                InitDone = true;
         }
Reason: