Конференция "Сети" » Для опытного глаза
 
  • Anatoly Podgoretsky © (23.10.07 16:17) [20]
    > Dennis I. Komarov  (23.10.2007 16:00:18)  [18]

    Какой еще хендл у процедуры?
  • Dennis I. Komarov © (23.10.07 16:33) [21]
    > [19] Сергей М. ©   (23.10.07 16:16)

    Нет, я отвернулся в сторону GetOverLappedResult.

    > Ты передал параметром overladded-структуру, в которой поле
    > hEvent = 0, вместо того чтобы содержать хэндл ивент-объекта.

    или в данном случае это будет @OnDirectoryChange?
    Или ивент-объект не есть процедура?
  • Сергей М. © (23.10.07 16:53) [22]

    > ивент-объект не есть процедура?
    >


    Конечно не процедура.

    ивент-объект создается вызовом CreateEvent()
  • Dennis I. Komarov © (23.10.07 17:14) [23]

    uses
    Main;

    { TThreadSend }
    type
    PFileNotifyInformation = ^TFileNotifyInformation;
    TFileNotifyInformation = packed record
      NextEntryOffset: DWORD;
      Action: DWORD;
      FileNameLength:DWORD;
      FileName: WideChar;
    end;

    procedure TThreadSend.Execute;

    var
    FTP: TIdFTP;

    SearchRec: TSearchRec;
    FindResult: Integer;

    ClientCode: string;
    FTPLogin: string;

    HomeDir: string;
    hDir: THandle;

    lpBuf: Pointer;
    lpOverlapped: POverlapped;
    hOnDirChange: THandle;

    begin
    { Place thread code here }
    FreeOnTerminate:=false;
    hOnDirChange:=CreateEvent(nil, false, true, PChar('OnChangeDirectory');
    hDir := CreateFile ( 'c:\test', GENERIC_READ, FILE_SHARE_READ, nil, OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);
    if hDir <> INVALID_HANDLE_VALUE then begin
      GetMem(lpBuf, 64*1204);
      GetMem(lpOverlapped, SizeOf(lpOverlapped));
      try
        ZeroMemory(lpBuf, SizeOf(lpBuf));
        lpOverlapped^.hEvent:=hOnDirChange;
        ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf), true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped, nil);
      finally
        FreeMem(lpBuf); FreeMem(lpOverlapped);

      end;

    end;
    end;
    end.



    Похоже? И как отлавливать теперь это событие?
  • Сергей М. © (24.10.07 09:21) [24]

    > GetMem(lpOverlapped, SizeOf(lpOverlapped));


    SizeOf(lpOverlapped) всегда равен 4, потому что это указатель.
    Либо разыменовывай его для взятия размера либо объяви переменную TOverlapped, тогда и GetMem не потребуется.


    > ZeroMemory(lpBuf, SizeOf(lpBuf));


    Здесь та же самая грубая ошибка.


    > как отлавливать теперь это событие?


    Любой удобной функцией ожидания - WaitForSingleObject, MsgWaitForMultipleObjects и иже с ними.
  • Dennis I. Komarov © (24.10.07 11:39) [25]

    > > GetMem(lpOverlapped, SizeOf(lpOverlapped));
    > > ZeroMemory(lpBuf, SizeOf(lpBuf));

    Ой мама, это как это я??? Это я не специально :)
  • Dennis I. Komarov © (24.10.07 16:57) [26]

    unit u_send;

    interface

    uses
     Classes, Windows, SysUtils, StrUtils, DateUtils,
     IdBaseComponent, IdComponent, IdTCPConnection, IdTCPClient, IdFTP, IniFiles;

    type
     OnDirectoryChange = procedure(Sender: TObject);

     TThreadSend = class(TThread)
     private
       { Private declarations }

     protected
       procedure Execute; override;

     end;

    var
     TCP: TIdTCPClient;
    implementation

    uses
     Main;
    { TThreadSend }
    type
     PFileNotifyInformation = ^TFileNotifyInformation;
     TFileNotifyInformation = packed record
       NextEntryOffset: DWORD;
       Action: DWORD;
       FileNameLength:DWORD;
       FileName: WideChar;
     end;

    procedure TThreadSend.Execute;

    var
     hDir: THandle;
     hDirChangeEvent: THandle;

     lpBuf: Pointer;
     lpOverlapped: POverlapped;
    begin
     { Place thread code here }
     FreeOnTerminate:=false;
     hDirChangeEvent:=CreateEvent(nil, false, true, PChar('OnChangeDirecory'));
     hDir := CreateFile ( 'c:\test', GENERIC_READ, FILE_SHARE_READ, nil,
             OPEN_EXISTING, FILE_FLAG_BACKUP_SEMANTICS or FILE_FLAG_OVERLAPPED, 0);
     if hDir <> INVALID_HANDLE_VALUE then begin
       GetMem(lpBuf, 64*1024);
       GetMem(lpOverlapped, SizeOf(lpOverlapped^));
       try
         ZeroMemory(lpBuf, 64*1024);
         lpOverlapped^.hEvent:=hDirChangeEvent;
         ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf), true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped, nil);
         while not Terminated do begin
           if WaitForSingleObject(hDirChangeEvent, 5000) = WAIT_OBJECT_0 then begin
             //Сюда должны попасть если в директории есть изменения
             //С помощью GetOverLappedResult
             //Если при чтении из lpBuf узнаем, что появился новый файл, тогда отправляем его споследствиями
             // Тут наверное надо обнулить lpBuf
             ReadDirectoryChangesW(hDir, lpBuf, SizeOf(lpBuf), true, FILE_NOTIFY_CHANGE_FILE_NAME, nil, lpOverlapped, nil);
           end;
         end;
       finally
         FreeMem(lpBuf); FreeMem(lpOverlapped);
       end;
     end;
    end;
    end.



    ??? :)
  • Сергей М. © (24.10.07 17:10) [27]

    > //Сюда должны попасть если в директории есть изменения


    Да.


    > //С помощью GetOverLappedResult
    >          //Если при чтении из lpBuf узнаем, что появился
    > новый файл, тогда отправляем его споследствиями


    Да, но при условии что ф-ция вернула True


    > // Тут наверное надо обнулить lpBuf


    Нафига ?

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


    > WaitForSingleObject(hDirChangeEvent, 5000)


    Тебя не смущает, что в течение этих 5 сек. таймаута ожидания сигнала ивента твой поток не будет реагировать на флаг Terminated ?
  • Сергей М. © (24.10.07 17:18) [28]

    > FreeOnTerminate:=false;


    Это лишнее.


    > GetMem(lpOverlapped, SizeOf(lpOverlapped^));


    Почему бы не сделать переменную Overlapped: TOverlapped локальной или полем класса ? Она ж крохотная, есть ли резон динамически распределять под нее память ?


    > CreateEvent(nil, false, true, PChar('OnChangeDirecory'));


    Почему true ? Он же у тебя сразу и просигналит, в то время как никаких изменений еще и в помине не было ...

    Да и имя ивента не обязательно.
  • Dennis I. Komarov © (25.10.07 10:21) [29]
    > И вообще заведи себе привычку вызывать WinAPI-функции как
    > функции - возвращаемые ими результаты следует анализировать,
    > ибо от них напрямую зависит дальнейшее правильное ветвление
    > алгоритма.

    Угу. Это же пока черновик :) Ну мне сейчас хочется разобраться в логике ассинхронного вызова.


    > > //Сюда должны попасть если в директории есть изменения
    >
    >
    > Да.

    Логично предположить, что при этом запрос в очереди уже отсутствует!?


    > > WaitForSingleObject(hDirChangeEvent, 5000)
    >
    >
    > Тебя не смущает, что в течение этих 5 сек. таймаута ожидания
    > сигнала ивента твой поток не будет реагировать на флаг Terminated
    > ?

    Ну вообще не смущает. Если при остановки вся это бодяга остановится через пять сек. меня это не очень расстроит, хотя сделую 1000 :) Уговорил.

    > > GetMem(lpOverlapped, SizeOf(lpOverlapped^));
    >
    >
    > Почему бы не сделать переменную Overlapped: TOverlapped
    > локальной или полем класса ? Она ж крохотная, есть ли резон
    > динамически распределять под нее память ?

    А разница?

    > > CreateEvent(nil, false, true, PChar('OnChangeDirecory')
    > );
    >
    >
    > Почему true ? Он же у тебя сразу и просигналит, в то время
    > как никаких изменений еще и в помине не было ...

    Да, тут не правильно перевел "F1" :)

    > Да и имя ивента не обязательно.

    Ну пускай будет :)
  • Сергей М. © (25.10.07 10:50) [30]

    > Логично предположить, что при этом запрос в очереди уже
    > отсутствует!?


    Конечно.
    Его результаты выбраны из очереди в указанный тобой буфер.


    > сделую 1000 :) Уговорил


    Да я тебя не уговаривал)
    Просто есть гораздо более изящные решения для преодоления этой "проблемы")
  • Dennis I. Komarov © (25.10.07 11:15) [31]
    > есть гораздо более изящные решения

    Пример? :)
  • Сергей М. © (25.10.07 12:55) [32]
    WaitFoeMultipleObjects, MsgWaitFoeMultipleObjects
  • Dennis I. Komarov © (25.10.07 13:29) [33]
    > [32] Сергей М. ©   (25.10.07 12:55)

    А в чем принципиальная разница? Чем оно "изящней"?
  • Сергей М. © (25.10.07 15:42) [34]
    Тем что поток приобретает способность немедленно реагировать не только на твой overlapped-ивент, но и на другие ивенты и/или сообщения.
  • Dennis I. Komarov © (25.10.07 16:48) [35]
    Я думал изящность имено в решении, а не в возможностях

    Есть приложение (возможно служба) задача которой транспортировка файлов с диска (не факт что локального) в сеть (FTP-сервер), и аналогично обратное. За каждое из действий отвечает свой поток. Ранее он (который отправлял) просто сканил папки на отправку (FindFirst/Next, ну сам видел). Более на него никаких функций не накладывается (разве что лог ). Другую смысловую нагрузку он не несет. Реакция на Terminated в течении секунды - это даже более чем :) .

    Непонятна такая вешь: Мы посавили запрос в очередь. По некоему событию, мы получаем факт, что этот запрос обработался и в указанном месте появились изменения. Данные об изменениях храняться по адресу lpBuf. Далее мы отправляем аналогичный запрос в очередь.
    1. На черта нам тогда функция GetOverlappedResult и
    2. В то время, пока мы обрабатываем ин-цию об изменениех, происходящие изменения не фиксируются?
  • Сергей М. © (26.10.07 08:08) [36]

    > 1. На черта нам тогда функция GetOverlappedResult


    Мало ли что могло произойти во время исполнения запроса !
    Ф-ция как раз и покажет, успешно ли выполнен запрос.
    А сигнал ивента лишь фиксирует факт завершения (успешного или неуспешного) асинхронной операции.


    > пока мы обрабатываем ин-цию об изменениех, происходящие
    > изменения не фиксируются?


    Нет. Поэтому следует как можно быстрей после сигнала ивента принять решение о постановке очередного запроса и лишь потом разбирать результаты текущего выполненного.
  • Dennis I. Komarov © (26.10.07 09:57) [37]
    > Нет. Поэтому следует как можно быстрей после сигнала ивента
    > принять решение о постановке очередного запроса и лишь потом
    > разбирать результаты текущего выполненного.

    Гм... Но для этого все равно понадобится какое то время, т.е.
    Получили сигнал события, далее по идее запроса в очереди нет, следует отправить его еще раз, отправлять с тем же указателем на буфер низя - можем потерять его, следовательно, предварительно надо сохранить данные, это потребует некоторого времени, за которое могут произойти изменения, начинаю подумывать о том, что "сканить" диск всетаки надежнее


    > Мало ли что могло произойти во время исполнения запроса
    > !
    > Ф-ция как раз и покажет, успешно ли выполнен запрос.
    > А сигнал ивента лишь фиксирует факт завершения (успешного
    > или неуспешного) асинхронной операции.


    hFile - чего она сюда хочет?
  • Сергей М. © (26.10.07 11:23) [38]

    > чего она сюда хочет?


    hDir твой она хочет.
  • Сергей М. © (26.10.07 11:44) [39]

    > "сканить" диск всетаки надежнее


    С чего бы ?

    Explorer, заметь, использует именно ReadDirectoryChangesW
 
Конференция "Сети" » Для опытного глаза
Есть новые Нет новых   [134431   +10][b:0][p:0.003]