Многопоточность в MQL через CreateThread WinAPI - страница 2

 

Благодарю за живой отклик

Переделал на потоках из STL по той же схеме, работает нормально как полностью в фоновом режиме когда управление сразу возвращается в индикатор, так и с ожиданием завершения

 
Stanislav Korotky:
А массив разве так должен передаваться в C++? Не нужно ли заменить double v[] на double *v в реализации random в DLL? Может из-за этого память портится.

Записи эквивалентны для С++, скорее для восприятия удобнее что передается массив или указатель на один объект, и v[1] эквивалентно *(v+1)

 
Ihor Herasko:

С Qt не работал, но что-то мне подсказывает, что:

не дает указаний на остановку потока, а только ждет его завершения. А раз так, то поток остается активным, из-за чего и происходит зависание.

По идее, QtConcurrent::run запускает функцию разово, т.е. как только функция завершает свою работу, то и завершается работа потока

waitForFinish как раз позволяет дождаться этого момента

И в процессе работы индикатора данные обновляются, график перерисовывается, что говорит о том что поток завершается и управление возвращается после waitForFinish

Как написал выше, переделал через stl и все норм теперь, какой-то конфликт с работой Qt в этой области, к сожалению, пока не понял что к чему

 
TheXpert:

ни перед функцией ни после? как ведет себя в дебаг режиме?

как вариант принтов может не быть как раз из-за того что терминал виснет, а виснет он скорее всего уже после OnDeinit, потому что я не верю что waitForFinished без задачи может устроить дедлок

В дебаге все норм, даже после завершения отладки пишется что индикатор удален, однако, окно индикатора с графиком остается и при попытке закрыть его терминал виснет

Какой-то конфликт с реализацией при помощи Qt

 

Реализация на stl

#include <chrono>
#include <thread>
#include <vector>

#include <windows.h>

using namespace std;

#define MQL_EXPORT extern "C" __declspec(dllexport)

void calc(HWND hwnd, double v[], int len)
{
    std::srand((unsigned int)time(0));
    std::this_thread::sleep_for(std::chrono::seconds(std::rand()%10));
    for (int i = 0; i < len; ++i) v[i] = std::rand()%500;
    PostMessageW(hwnd, WM_TIMER, 0, 0);
}

MQL_EXPORT int add(int a, int b)
{
    return a+b;
}

MQL_EXPORT void begin_calculation(HWND hwnd, double v[], int len)
{
    std::thread thr(calc, hwnd, v, len);
}
#property strict
#property indicator_separate_window
#property indicator_buffers 1
#property indicator_plots   1
//--- plot L
#property indicator_label1  "L"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1

#import "dlltest3.dll"
   int add(int a, int b);
   void begin_calculation(int hwnd, double &v[], int len);
#import

double L[];

int hwnd;

int OnInit()
{
   SetIndexBuffer(0, L);
   hwnd = (int)ChartGetInteger(0, CHART_WINDOW_HANDLE);
   return(INIT_SUCCEEDED);
}

void OnTimer()
{
   static ulong last = GetMicrosecondCount();
   ulong cur = GetMicrosecondCount();
   Print("Timer ", cur - last);
   last = cur;
}

void OnDeinit(const int reason)
{
   Print(__FUNCTION__, " ", __LINE__);
}

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[])
{   
   static int it = 0;
   Print(__LINE__);
   
   int res = add(it, it);
   ulong start = GetMicrosecondCount();
   begin_calculation(hwnd, L, ArraySize(L));
   Comment(++it, " ", res, " ", GetMicrosecondCount() - start);
   Print(__LINE__);
   return(rates_total);
}

Тут конечно надо добавить синхронизацию, в OnDeinit поставить ожидание завершения потока и т.п.

Еще по хорошему надо данные готовить отдельно и потом копировать в буфер индикатора когда они готовы, но вроде как не критично

 

Кому интересно в тему углубиться, рекомендую почитать https://thispointer.com/c11-multithreading-tutorial-series/

Там много статей о многопоточности и какими инструменты для этого применяются

Открыл для себя много нового

Причина обращения: