Доступ к файлам - страница 2

 

Решил довести-таки эксперимент до логического конца. Нужно было выяснить следующий момент: если файл открыт первым скриптом, то второму скрипту есть добро открыть его для записи, или только для чтения? Для этого изменил коды скриптов. В первом изменил время сна и текст вписываемой в файл строки. Во второй скрипт добавил функцию Кима, добавляющую строку в конец файла. (см. коды ниже). Кинул первый скрипт на график. Щёлкнул правой кнопкой мыши по графику и убедился, что в контекстном меню присутствует сообщение о выполняющемся скрипте. Переключился на другой график, кинул на него второй скрипт, получил Алерт, что файл свободен. Открыл наш 1.txt - строка второго скрипта на месте - пока первый скрипт спал, второй скрипт добавил в файл строку, сохранился и выгрузился из оперативной памяти. Закрыл 1.txt. Переключился на график с первым скриптом, дождался алерта с сообщением, что удержание файла закончено. Открыл снова документ 1.txt. Результат - ну просто сказка с грустным концом. Сообщение первого скрипта добавилось не в последнюю строку, а заменило собой кусок сообщения второго скрипта. От сообщения второго скрипта остались только две буквы на следующей строчке. На следующей потому, что первый скрипт помимо самой строки добавил и служебные символы конца строки и перевода каретки на новую строку (символ абзаца).

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

//+------------------------------------------------------------------+
//|                                                     OpenFile.mq4 |
//|                                           Copyright 2012, DRKNN. |
//|                                                    drknn@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012,  DRKNN."
#property link      "drknn@mail.ru"

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start(){
  string FlName="1.txt";
  int file_handle;
  file_handle=FileOpen(FlName, FILE_CSV|FILE_READ|FILE_WRITE, " ");
  if (file_handle>0){
                FileSeek(file_handle,0,SEEK_END);
                if(FileWrite(file_handle,"Строка из скрипта  OpenFile")<0){
                  Alert(" ============================================== ");
                  Alert("Ошибка № ",GetLastError()," при попытке добавить строку в файл111");
                }
                else{
                 Sleep(20000);
                }
        }
        else{
          Alert(" ============================================== ");
          Alert("Ошибка ",GetLastError()," - Не удалось открыть файл ",FlName);
        }
  FileClose(file_handle);
  Alert(" ============================================== ");
  Alert("Удержание файла окончено");
//----
   return(0);
  }
//+------------------------------------------------------------------+
//+------------------------------------------------------------------+
//|                                                 SkolkoZanjat.mq4 |
//|                                           Copyright 2012, DRKNN. |
//|                                                    drknn@mail.ru |
//+------------------------------------------------------------------+
#property copyright "Copyright 2012, DRKNN."
#property link      "drknn@mail.ru"
#property show_inputs
#include <FileStatus_DLL.mqh>
string ScriptName=" SkolkoZanjat";
extern string FileName="1.txt";

//+------------------------------------------------------------------+
//| script program start function                                    |
//+------------------------------------------------------------------+
int start(){

   string Otkuda=TerminalPath()+"\\experts\\files\\"+FileName;
   
   if(!FileStatus(Otkuda)){
      Alert("Файл открыт другой программой");
   }
   else{
     Alert("Файл свободен"); 
                 AddLineInFile(FileName,"Строка из скрипта  SkolkoZanjat");
   }

   return(0);
  }
//+------------------------------------------------------------------+
//+------------------------- AddLineInFile() ----------------------------
//| Дописывание строки в конец файла
//+---------------------------------
void AddLineInFile(string FlName, string Text){
  string        Str,NameFunction="AddLineInFile()";
  int file_handle;
  file_handle=FileOpen(FlName, FILE_CSV|FILE_READ|FILE_WRITE, " ");
        if (file_handle>0){
                FileSeek(file_handle,0,SEEK_END);
                if(FileWrite(file_handle,Text)<0){
                  Print(" ============================================== ");
                        Print("Ошибка № ",GetLastError()," при попытке добавить строку: ", Text," в файл: ",FlName);
                        Print(" ============== ",NameFunction," ============== ");
                }
                FileClose(file_handle);
        }
        else{
                Print(" ============================================== ");
          Print("Ошибка ",GetLastError()," - Не удалось открыть файл ",FlName);
                Print(" ============== ",NameFunction," ============== ");
   }
}
//--------------------------------------------------------------------------- 
Файлы:
 
 
Разработчики, добавьте пожалуйста мои выводы в справку метаэдитора - ну ведь кому-то время жизни сэкономим и силы. И возможно даже не одной сотне человек.
 
Integer:

Эта функция действительно позволяет организовать семафор.

Ого, век живи, век учись.
 
А покажите-ко кто-нибудь на примере кода, в чём изюминка той самой семафорной функци? Что-то её надобность вот так сходу и не видна. Я. например, сделал семафор и без неё и он вполне работает. Мож я чего-то недопонимаю. Если нужно, то код своего семафора покажу - не вопрос - да и нет там ни чего сверхъестественного - всё просто как три копейки.
 
drknn:
А покажите-ко кто-нибудь на примере кода, в чём изюминка той самой семафорной функци? Что-то её надобность вот так сходу и не видна. Я. например, сделал семафор и без неё и он вполне работает. Мож я чего-то недопонимаю. Если нужно, то код своего семафора покажу - не вопрос - да и нет там ни чего сверхъестественного - всё просто как три копейки.
Семафор на неатомарном уровне - не семафор. Обязательно будут коллизии.
 
Zhunko:
Семафор на неатомарном уровне - не семафор. Обязательно будут коллизии.


Столкновения интересов советников будут в любом случае, если они используют доступ к одному и тому же текстовому документу. Есть очень малая доля вероятности, что тик по двум валютным парам придёт миллисекунда в миллисекунду (в чём я вообще сомневаюсь). И тогда два эксперта попытаются одновременно внести изменения в текстовый документ. Скажите, как может помочь в этом случае функция GlobalVariableSetOnCondition() ? Да ни как - два эксперта одновременно попытаются изменить значение переменной глобального уровня.

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

        // ===============================================================================================
        // ==================== Блок семафора ============================================================
        // ===============================================================================================
        if(!GlobalVariableCheck(Global_Value)){GlobalVariableSet(Global_Value,0);}
        Index=0;
        while(true){
                if(GlobalVariableGet(Global_Value)<=0){//семафор зелёный - можно торговать
                        GlobalVariableSet(Global_Value,1);// включаем красный для всех прочих копий советника
                        break;
                }
                else{
                        Sleep(1000);//ждём 1 секунду
                        Index++;
                        if(Index>=120){// превышен предел ожидания в 2 минуты (60*2=120 секунд)
                                Print("Советник ",NameExpert," на инструменте ",Symbol()," прождал зелёного цвета семафора 2 минуты. Работа на текущем тике прервана. Ждём новый тик.");
                                return(0);
                        }
                }
        }
        // ===============================================================================================
После этого блока кода нужно просто не забыть перед каждым ретурном, прерывающим работу советника, установить переменную глобального уровня в отрицательное положение.
 
Администратор, поставьте пожалуйста в настройках форума табуляцию, размером в 2-3 символа. Она сейчас стоит = 7 - очень неудобно так табулировать - посмотрите выше - какой размазанный по горизонтали из-за этого получается код.
 
drknn:


Столкновения интересов советников будут в любом случае, если они используют доступ к одному и тому же текстовому документу. Есть очень малая доля вероятности, что тик по двум валютным парам придёт миллисекунда в миллисекунду (в чём я вообще сомневаюсь). И тогда два эксперта попытаются одновременно внести изменения в текстовый документ. Скажите, как может помочь в этом случае функция GlobalVariableSetOnCondition() ? Да ни как - два эксперта одновременно попытаются изменить значение переменной глобального уровня.

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

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

А можно более развёрнутый ответ? Ну как для ребёнка.