MQL4 потоки (thread/fork), это возможно? - страница 4

 
Yuriy Asaulenko:

Пока Ренат спит. )) 

Я делаю в ДЛЛ через коллекции. Один поток (или потоки) пишет данные в коллекцию(и), другие эти коллекции читают начиная с конца, и удаляют из коллекции уже прочитанное. Потоки никак не взаимодействуют друг с другом. И читаются самые новые данные, но, в итоге все данные будут прочитаны.

Юрий, просто скелет примера, без внутренних алгоритмов вашего проекта. Буду вам признателен.

 

Вот это мне и нужно :), это отрывок статьи:

Под асинхронным программированием я понимаю стиль программирования, который можно охарактеризовать следующим выражением: “дал задачу и забыл”. Т.е. это такой стиль при котором все тяжеловесные задачи исполняются в отличном от вызывающего потоке, и результат выполнения которых может быть получен, вызывающим потоком, когда он того пожелает(при условии, что результат доступен).

 
Farkhat Guzairov:

Юрий, просто скелет примера, без внутренних алгоритмов вашего проекта. Буду вам признателен.

Как это? Все чистить и в разных классах? Не, не смогу, просто долго.

Сделано на смеси managed-unmanaged C++ c NET библиотеками. Могу попробовать экземплы в MSDN найти. Все, собственно, на их базе.


System.Collections, System.Threading,класс Thread - пожалуй все, что нужно.
 
Yuriy Asaulenko:

Как это? Все чистить и в разных классах? Не, не смогу, просто долго.

Сделано на смеси managed-unmanaged C++ c NET библиотеками. Могу попробовать экземплы в MSDN найти. Все, собственно, на их базе.

Да, хотя бы направление, чтобы не тратить время на варианты. Просто печально, я только портировал проект из С++ в MQl и теперь придется опять все переписывать на С++ ((((, это меня бесит.

Просто хочу оптимизировать расчетную часть(математику), а боту дать только готовый результат и для управления ордерами.
 
Farkhat Guzairov:

Да, хотя бы направление, чтобы не тратить время на варианты. Просто печально, я только портировал проект из С++ в MQl и теперь придется опять все переписывать на С++ ((((, это меня бесит.

System.Collections, System.Threading,класс Thread - пожалуй все, что нужно.

Все доки вообще здесь - https://msdn.microsoft.com/ru-ru/library/system.threading.thread(v=vs.110).aspx

Описание коллекций - https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/concepts/collections

 
Farkhat Guzairov:

Просто хочу оптимизировать расчетную часть(математику), а боту дать только готовый результат и для управления ордерами.

Давайте в личку перейдем.)

 
Yuriy Asaulenko:

Давайте в личку перейдем.)

Я не против.
 
Yuriy Asaulenko:

Сделано на смеси managed-unmanaged C++ c NET библиотеками. Могу попробовать экземплы в MSDN найти. Все, собственно, на их базе.

System.Collections, System.Threading,класс Thread - пожалуй все, что нужно.
Farkhat Guzairov:
Соглашусь, пока иных способов не вижу. Хотя можно извращаться с глобальными переменами, но это крайний случай.

Вы не тем занимаетесь. Работа с потоками и прочими извратами - это как стрелять по воробью из пушки. Вопрос: Зачем? Вы сюда пришли писать роботов для зарабатывания денег, а не этюды по программированию решать.

Есть конкретная задача:

Farkhat Guzairov:

В моем случае не было попытки "ускорить", все достаточно тривиально, просто хотел избавить эксперт от вычислений которые мешают ему, в реальном режиме времени принимать решения (открытие/закрытие/модификация) по позициям, пока он находится в состоянии перерасчет.

Для этого мне нужен асинхронный поток.

Вот ее решить обычными средствами MQL4 достаточно просто. Для этого необходимо разорвать цикл расчета в OnCalculate на несколько итераций, и никаких извратов с потоками для этого делать не нужно.

Я написал рабочий прототип из двух частей: индикатора и эксперта. Индикатор имитирует тяжелый расчет, эксперт получает значения этого индикатора, паралельно сигнализируя в Comment сколько баров из общего количества рассчитано.

Индикатор

//+------------------------------------------------------------------+
//|                                               SlowAsynchTest.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 1
#property indicator_plots 1
#property indicator_type1 DRAW_LINE
#property indicator_color1 clrRed
#property indicator_width1 2

input int MaPeriod = 12;

double sma_out[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
//--- indicator buffers mapping
   SetIndexBuffer(0, sma_out);   
//---
   return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
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[])
{
   int msk = GetTickCount();
   ArraySetAsSeries(sma_out, false);
   printf("OnCalculate run...");
   for(int i = prev_calculated; i < rates_total; i++)
   {
      
      int shift = rates_total - i;
      //-- Имитация бурной деятельности (Sleep  в индикаторах не работает)
      while(MathRand() != 2938 && MathRand() != 15000)
      {
         sma_out[i] = iMA(Symbol(), Period(), MaPeriod, 0, MODE_SMA, PRICE_CLOSE, shift);
      }
      sma_out[i] = iMA(Symbol(), Period(), MaPeriod, 0, MODE_SMA, PRICE_CLOSE, shift);
      if(i>0 && i%1000==0)
         return ++i; // Принудительный возврат в вызывающий поток 
   }
   if(prev_calculated == 0)
      printf("Milliseconds count: " + (string)(GetTickCount()-msk));
   return(rates_total);
}
//+------------------------------------------------------------------+

Эксперт:

//+------------------------------------------------------------------+
//|                                           AsychIndicatorTest.mq4 |
//|                        Copyright 2015, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "Copyright 2015, MetaQuotes Software Corp."
#property link      "http://www.mql5.com"
#property version   "1.00"
#property strict

int prev_calculated = 0;
//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
  {
//--- create timer
   EventSetMillisecondTimer(250);
//---
   return(INIT_SUCCEEDED);
  }
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//--- destroy timer
   EventKillTimer();
}
//+------------------------------------------------------------------+
//| Timer function                                                   |
//+------------------------------------------------------------------+
void OnTimer()
{
//---
   int count = iBars(Symbol(), Period());
   int calculated = prev_calculated;
   for(; calculated < count; calculated++)
   {
      int shift = count - calculated;
      double value = iCustom(Symbol(), Period(), "SlowAsynchTest", 128, 0, shift);
      if(value == EMPTY_VALUE)
         break;   
   }
   Comment("Подсчитано " + (string)calculated + " баров из " + (string)count);
   prev_calculated = calculated;
}
//+------------------------------------------------------------------+

Вот результат:


Конечно, доделывать здесь еще много, но у Вас же 20 лет программисткого стажа.

Еще раз поймите асинхронность != многопоточность. Асинхронность - это паттерн программирования, вид алгоритма, а не какая-то крутая внешняя библиотека типа System.Threading.

 
Vasiliy Sokolov:

кстати в индикаторах можно использовать значение 

return(rates_total);

и на следующем вызове получить его в 

prev_calculated

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

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[])
  {
//---
   int NumberOnCalculate=9999;
   switch(prev_calculated)
     {
      case 0:        //--- Первый вызов индикатора или смена таймфрейма или подгрузка данных из истории
         NumberOnCalculate=123;
         break;
      case 123:      //--- второй вызов индикатора
                     //--- расчеты .....
         NumberOnCalculate=223;
         break;
      case 223:      //--- третий вызов индикатора
                     //--- расчеты .....
         NumberOnCalculate=323;
         break;
      case 323:      //--- четвертый вызов индикатора
                     //--- расчеты .....
         NumberOnCalculate=9999;
         break;
      default:       NumberOnCalculate=9999;
      break;
     }
   return(NumberOnCalculate); // вернем номер точки входа для следующего вызова индикатора
  }
 
Оригинально есть над чем подумать! Возьму на заметку.
Причина обращения: