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

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

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

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 25.10.2012, 00:32   #1
admigator
 
Регистрация: 12.05.2010
Сообщений: 5
По умолчанию Мониторинг изменений на USB (многопоточность)

Привет всем!
На просторах форумов накопал две программки:

1- определяет подключения USB накопителей в систему (и не только ) (setupAPI.pas)
2- мониторит изменения в папке (wfsU.pas)

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

Код:
procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
создается поток, который и мониторит изменения в папке.

А сама функция создает обьект - екземпляр класса TWFS

Код:
procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
begin

 WFS:=TWFS.Create(pName, pFilter, pSubTree, pInfoCallBack);
 //th_no=th_no+1;
end;

А вот собственно сам класс(обьявление)

Код:
 TWFS = class(TThread)
  private
    FName           : string;
    FFilter         : Cardinal;
    FSubTree        : boolean;
    FInfoCallBack   : TWatchFileSystemCallBack;
    FWatchHandle    : THandle;
    FWatchBuf       : array[0..4096] of Byte;
    FOverLapp       : TOverlapped;
    FPOverLapp      : POverlapped;
    FBytesWritte    : DWORD;
    FCompletionPort : THandle;
    FNumBytes       : Cardinal;
    FOldFileName    : string;
    function CreateDirHandle(aDir: string): THandle;
    procedure WatchEvent;
    procedure HandleEvent;
  protected
    procedure Execute; override;
  public
    constructor Create(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
    destructor Destroy; override;
  end;
Монитор изменения на дисках работает нармально. Если вставляю две флешки, тоже все ок. Проблемма при извлечении. На кнопку "извлечь" выполняю процедуру StopWatch

она делает следущее:
Код:
procedure StopWatch
var
  Temp : TWFS;
begin
  if Assigned(WFS) then
  begin
   PostQueuedCompletionStatus(WFS.FCompletionPort, 0, 0, nil);
   Temp := WFS;
   WFS:=nil;
   Temp.Terminate;
  end;
end;
т.е. останавливает поток и "убивает" обьект WFS. Но останавливает только последний поток. А первый остается.

Вопрос. Как остановить первый поток. И в случае трех флешек при извлечении останавливать нужный поток.
Спасибо.
В атачче исходники.
Вложения
Тип файла: rar dev.rar (217.1 Кб, 16 просмотров)

Последний раз редактировалось admigator; 25.10.2012 в 12:18.
admigator вне форума Ответить с цитированием
Старый 25.10.2012, 12:47   #2
xoodoo
Форумчанин
 
Регистрация: 11.04.2012
Сообщений: 212
По умолчанию

Ссылки на созданные объекты-потоки записывай в отдельные элементы заранее подготовленного массива, а не в одну и ту же глобальную переменную WPS.
xoodoo вне форума Ответить с цитированием
Старый 25.10.2012, 13:15   #3
admigator
 
Регистрация: 12.05.2010
Сообщений: 5
По умолчанию

Пробую так
в глобальных переменных
вместо
Код:
var
 WFS : TWFS;
ставлю
Код:
var
  ArrWFS : array of TWFS = nil;
  Thread_counter: integer = 0;
потом

Код:
procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
begin
 ArrWFS[Thread_counter]:=TWFS.Create(pName, pFilter, pSubTree, pInfoCallBack);
 Thread_counter:=Thread_counter+1;
end;
ошибка в конструкторе после Resume "Access violation at adress 0045E27D in vodule 'Project1.exe' Write of adress 00000000"

Код:
constructor TWFS.Create(pName: string; pFilter: cardinal;
  pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
begin
  inherited Create(True);
  FreeOnTerminate:=True;
  FName:=IncludeTrailingBackslash(pName);
  FFilter:=pFilter;
  FSubTree:=pSubTree;
  FOldFileName:=EmptyStr;
  ZeroMemory(@FOverLapp, SizeOf(TOverLapped));
  FPOverLapp:=@FOverLapp;
  ZeroMemory(@FWatchBuf, SizeOf(FWatchBuf));
  FInfoCallBack:=pInfoCallBack;
  Resume
end;
пробую использовать TList

Код:
var
FThreads: TList;

procedure StartWatch(pName: string; pFilter: cardinal; pSubTree: boolean; pInfoCallBack: TWatchFileSystemCallBack);
begin
  FThreads := TList.Create;
  WFS:=TWFS.Create(pName, pFilter, pSubTree, pInfoCallBack);
  FThreads.Add(WFS);
end;
но не пойму как мне из этого списка потом получить поток соответствующий моей флешке.

Последний раз редактировалось admigator; 25.10.2012 в 13:29.
admigator вне форума Ответить с цитированием
Старый 25.10.2012, 15:00   #4
xoodoo
Форумчанин
 
Регистрация: 11.04.2012
Сообщений: 212
По умолчанию

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

Цитата:
ошибка в конструкторе после Resume
Да не в конструкторе она)

Ты пытаешься присвоить некое значение (неважно какое, в дан.случае - ссылку на экземпляр созданного объекта-потока) несуществующему элементу массива.

Цитата:
пробую использовать TList
Те же грабли - при каждом вызове StartWatch() ты затираешь значение поля FTreads, безвозвратно теряя в памяти предудущий объект-список (на который ссылалось поле после предыдущего вызова StartWatch).

Цитата:
как мне из этого списка потом получить поток соответствующий
У тебя же каждый создаваемый объект-поток именован, причем уникально как можно предположить.
Т.е. каждый поток имеет уникальный строковый атрибут - имя.
Прямо-таки напрашивается простейшее решение - TStringList. Каждый элемент этого списка способен хранить строку и ассоццированный с этой строкой указатель. Значению указателя можно присвоить ссылку на объект-поток, которую возвращает конструктор TWPS. Далее при вызове StopWatch найти соотв.элемент списка по имени потока и получить ссылку на этот поток не составляет никакой сложности.
xoodoo вне форума Ответить с цитированием
Старый 25.10.2012, 15:31   #5
admigator
 
Регистрация: 12.05.2010
Сообщений: 5
По умолчанию

Цитата:
Сообщение от xoodoo Посмотреть сообщение
Ты взялся за не самые тривиальную технологию - мультипоточность, не зная даже азов.
Таки да :-(
Цитата:
Прямо-таки напрашивается простейшее решение - TStringList. Каждый элемент этого списка способен хранить строку и ассоццированный с этой строкой указатель. Значению указателя можно присвоить ссылку на объект-поток, которую возвращает конструктор TWPS. Далее при вызове StopWatch найти соотв.элемент списка по имени потока и получить ссылку на этот поток не составляет никакой сложности.
Не хватает опыта чтоб такое написать. В Delphi лет 8 назад сидел. А тут такая задача. Если будет время написать в виде кода. Спасибо
admigator вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Отображение изменений Green4el JavaScript, Ajax 3 17.04.2012 17:39
Сохранение изменений Dmitrov БД в Delphi 2 16.05.2011 09:25
Сохранение изменений Dmitrov Помощь студентам 0 15.05.2011 13:36
Отслеживание изменений Fezdipekla Microsoft Office Access 3 09.07.2010 22:56
внесение изменений в реестр Experementator Общие вопросы Delphi 2 19.11.2008 12:03