Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.11.2011, 11:27   #1
[MoNAMur]
читер
Форумчанин
 
Аватар для [MoNAMur]
 
Регистрация: 05.10.2009
Сообщений: 150
Вопрос Потоки: неверный дескриптор(6) при создании потока

Поток должен мониторить состояние файлов в директории.

создание потока:
Код:
procedure TForm2.Button1Click(Sender: TObject);
var
    mon : TFileMon;
begin
    mon := TFileMon.Create(Edit1.Text);
    mon.Priority := tplower;
    mon.startDetecting;
end;
на строчке end; код останавливается с "неверный дескриптор(6)"

код потока
Код:
unit FilesMonitor;

interface

uses Classes, SysUtils, Windows, ShellAPI, Dialogs, Forms;

type
    PFileNotifyInformation = ^TFileNotifyInformation;
    TFileNotifyInformation = record
        NextEntryOffset: DWORD;
        Action: DWORD;
        FileNameLength: DWORD;
        FileName: array [0..MAX_PATH - 1] of WideChar;
end;

type TFileMon = class(TThread)
  private
        DirectoryMonitoring : THandle;
        FilesListing : TStringList;
  protected
        procedure Execute; override;
  public
        constructor Create(DirPath:string);
        destructor  Destroy; override;
        procedure addFileToListing(FileName: string);
        procedure deleteFileFromListing(FileName: string);
        procedure changeFileAction(FileName: string);
        procedure clearFilesListing;
        procedure detectChanges;
        procedure startDetecting;
end;

const
  FilterNotify =  FILE_NOTIFY_CHANGE_FILE_NAME or
            FILE_NOTIFY_CHANGE_DIR_NAME or
            FILE_NOTIFY_CHANGE_ATTRIBUTES or
            FILE_NOTIFY_CHANGE_SIZE or
            FILE_NOTIFY_CHANGE_LAST_WRITE or
            FILE_NOTIFY_CHANGE_LAST_ACCESS or
            FILE_NOTIFY_CHANGE_CREATION or
            FILE_NOTIFY_CHANGE_SECURITY;

implementation

constructor TFileMon.Create(DirPath:string);
begin
     DirectoryMonitoring := CreateFile(PWideChar(DirPath),
                        GENERIC_READ,
                        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS,
                        0);
     FilesListing := TStringList.Create;
{
при пошаговом выполнении видно что DirectoryMonitoring содержит нормальный указатель на папку. FilesListing создается тоже нормально.
}
end;

destructor TFileMon.Destroy;
begin
    FilesListing.Free;
    if DirectoryMonitoring <> INVALID_HANDLE_VALUE then
       CloseHandle(DirectoryMonitoring);
    inherited;
end;

procedure TFileMon.addFileToListing(FileName:string);
begin
      showmessage('добавлен файл '+ FileName);
     {
     if FilesListing.IndexOf(FileName) = -1 then
        FilesListing.Add(FileName);
     }
end;

procedure TFileMon.deleteFileFromListing(FileName: string);
begin
     showmessage('удален файл '+ FileName);
     {
     if FilesListing.IndexOf(FileName) <> -1 then
        FilesListing.Delete(FilesListing.IndexOf(FileName));
     }
end;

procedure TFileMon.changeFileAction(FileName: string);
begin
    showmessage('изменен файл '+ FileName);
end;


procedure TFileMon.clearFilesListing;
begin
     FilesListing.Clear;
end;

procedure TFileMon.detectChanges; 
var
    Notify: TFileNotifyInformation;
    BytesReturned: DWORD;
begin
    if DirectoryMonitoring <> INVALID_HANDLE_VALUE then
      try
          if not ReadDirectoryChangesW(DirectoryMonitoring,
                                      @Notify,
                                      SizeOf(TFileNotifyInformation),
                                      False,
                                      FilterNotify,
                                      @BytesReturned,
                                      nil,
                                      nil) then
              raise Exception.Create(SysErrorMessage(GetLastError))
          else
              case Notify.Action of
                  FILE_ACTION_ADDED: addFileToListing(Notify.FileName);
                  FILE_ACTION_REMOVED: deleteFileFromListing(Notify.FileName);
                  FILE_ACTION_MODIFIED: changeFileAction(Notify.FileName);
              //    FILE_ACTION_RENAMED_OLD_NAME: showmessage('Old Name file' + Notify.FileName);
              //    FILE_ACTION_RENAMED_NEW_NAME: showmessage('New Name file' + Notify.FileName);
              end;
      except
          //   
      end;
end;

procedure TFileMon.Execute;
begin
     while true do
      begin
        synchronize(detectChanges);
      end;
end;

procedure TFileMon.startDetecting;
begin
    Execute;
end;

end.
В чем ошибка, подскажите?
$me = $me == $me ? $me : $me;

Последний раз редактировалось [MoNAMur]; 08.11.2011 в 11:34.
[MoNAMur] вне форума Ответить с цитированием
Старый 08.11.2011, 11:34   #2
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Код:
procedure TFileMon.startDetecting;
begin
    Execute;
end;
где ж вы так учились потоки делать?
Код:
procedure TFileMon.Execute;
begin
     while true do
      begin
        synchronize(detectChanges);
      end;
end;
мдя...и толку от потока тогда?
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Старый 08.11.2011, 11:35   #3
[MoNAMur]
читер
Форумчанин
 
Аватар для [MoNAMur]
 
Регистрация: 05.10.2009
Сообщений: 150
По умолчанию

Пепел Феникса, покажи как правильно
$me = $me == $me ? $me : $me;
[MoNAMur] вне форума Ответить с цитированием
Старый 08.11.2011, 11:53   #4
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

Код:
unit FilesMonitor;

interface

uses Classes, SysUtils, Windows, ShellAPI, Dialogs, Forms;

type
    PFileNotifyInformation = ^TFileNotifyInformation;
    TFileNotifyInformation = record
        NextEntryOffset: DWORD;
        Action: DWORD;
        FileNameLength: DWORD;
        FileName: array [0..MAX_PATH - 1] of WideChar;
end;

type TFileMon = class(TThread)
  private
        DirectoryMonitoring : THandle;
        FilesListing : TStringList;
  protected
        procedure Execute; override;
  public
        constructor Create(DirPath:string);
        destructor  Destroy; override;
        procedure addFileToListing(FileName: string);
        procedure deleteFileFromListing(FileName: string);
        procedure changeFileAction(FileName: string);
        procedure detectChanges;
end;

const
  FilterNotify =  FILE_NOTIFY_CHANGE_FILE_NAME or
            FILE_NOTIFY_CHANGE_DIR_NAME or
            FILE_NOTIFY_CHANGE_ATTRIBUTES or
            FILE_NOTIFY_CHANGE_SIZE or
            FILE_NOTIFY_CHANGE_LAST_WRITE or
            FILE_NOTIFY_CHANGE_LAST_ACCESS or
            FILE_NOTIFY_CHANGE_CREATION or
            FILE_NOTIFY_CHANGE_SECURITY;

implementation

constructor TFileMon.Create(DirPath:string);
begin
     inherited Create(false);
     DirectoryMonitoring := CreateFile(PWideChar(DirPath),
                        GENERIC_READ,
                        FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
                        nil,
                        OPEN_EXISTING,
                        FILE_FLAG_BACKUP_SEMANTICS,
                        0);
     FilesListing := TStringList.Create;
     Resume;
end;

destructor TFileMon.Destroy;
begin
    FilesListing.Free;
    if DirectoryMonitoring <> INVALID_HANDLE_VALUE then
       CloseHandle(DirectoryMonitoring);
    inherited;
end;

procedure TFileMon.addFileToListing(FileName:string);
begin
      showmessage('добавлен файл '+ FileName);
     {
     if FilesListing.IndexOf(FileName) = -1 then
        FilesListing.Add(FileName);
     }
end;

procedure TFileMon.deleteFileFromListing(FileName: string);
begin
     showmessage('удален файл '+ FileName);
     {
     if FilesListing.IndexOf(FileName) <> -1 then
        FilesListing.Delete(FilesListing.IndexOf(FileName));
     }
end;

procedure TFileMon.changeFileAction(FileName: string);
begin
    showmessage('изменен файл '+ FileName);
end;

procedure TFileMon.detectChanges; 
var
    Notify: TFileNotifyInformation;
    BytesReturned: DWORD;
begin
    if DirectoryMonitoring <> INVALID_HANDLE_VALUE then
      try
          if not ReadDirectoryChangesW(DirectoryMonitoring,
                                      @Notify,
                                      SizeOf(TFileNotifyInformation),
                                      False,
                                      FilterNotify,
                                      @BytesReturned,
                                      nil,
                                      nil) then
              raise Exception.Create(SysErrorMessage(GetLastError))
          else
              case Notify.Action of
                  FILE_ACTION_ADDED: addFileToListing(Notify.FileName);
                  FILE_ACTION_REMOVED: deleteFileFromListing(Notify.FileName);
                  FILE_ACTION_MODIFIED: changeFileAction(Notify.FileName);
              //    FILE_ACTION_RENAMED_OLD_NAME: showmessage('Old Name file' + Notify.FileName);
              //    FILE_ACTION_RENAMED_NEW_NAME: showmessage('New Name file' + Notify.FileName);
              end;
      except
          //   
      end;
end;

procedure TFileMon.Execute;
begin
     while not Terminated do
      begin
        detectChanges;
      end;
end;

end.
так оно будет работать поидее(у меня нет Делфи и в ней давно уже серьезно не пишу),хотя тут лучше в файл выводить.
и вообще я обычно если надо контролировать поток извне, делаю чтото типа стека команд для потока.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.

Последний раз редактировалось Пепел Феникса; 08.11.2011 в 11:58.
Пепел Феникса вне форума Ответить с цитированием
Старый 08.11.2011, 12:05   #5
[MoNAMur]
читер
Форумчанин
 
Аватар для [MoNAMur]
 
Регистрация: 05.10.2009
Сообщений: 150
По умолчанию

Спасибо, теперь все хорошо работает.
$me = $me == $me ? $me : $me;

Последний раз редактировалось [MoNAMur]; 08.11.2011 в 12:08.
[MoNAMur] вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Ошибка при работе с canvas "Неверный дескриптор" Алекс Ялта Gamedev - cоздание игр: Unity, OpenGL, DirectX 17 13.06.2011 22:32
ошибки при вызове формы из потока пауэрлифтинг Общие вопросы Delphi 0 24.03.2010 23:04
неверный формат при записи потока в файл Владимир1988 Помощь студентам 5 01.02.2010 12:45
Функция open() возвращает неверный дескриптор devl Общие вопросы C/C++ 8 12.01.2010 20:36
Из за чего пишет неверный дескриптор AquaKlaster Общие вопросы Delphi 9 12.09.2009 16:23