Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2006.08.20;
Скачать: CL | DM;

Вниз

Как остановить выполнение потока   Найти похожие ветки 

 
sally   (2006-04-26 17:49) [0]

Есть Thread, в котором реализована некоторая процедура, в которой используется API функция
DeviceIoControl (Handle, FSCTL_MOVE_FILE, ...);
Если файл "большой", т.е. занимает много кластеров, то до тех пор пока он не будет перемещен никакой Terminate не помогает. Можно ли как то прервать выполнение данной функции(DeviceIoControl)?


 
Игорь Шевченко ©   (2006-04-26 17:51) [1]


> Если файл "большой", т.е. занимает много кластеров, то до
> тех пор пока он не будет перемещен никакой Terminate не
> помогает


Смотреть в сторону параметра Overlapped в функции DeviceIoControl.


> Можно ли как то прервать выполнение данной функции(DeviceIoControl)?


CancelIO(Ex) ?


 
sally   (2006-04-27 12:43) [2]

Спасибо. Попробовал, но чего то не получается
делаю так:

private
   lSync: OVERLAPPED;
на создании потока
  FillChar(lSync, SizeOf(TOverlapped), 0);
  lSync.hEvent := CreateEvent(nil, true, FALSE, #0);

далее
 MoveParams.FileHandle := CreateFile(PAnsiChar(AFile.FileName),        FILE_READ_ATTRIBUTES,     FILE_SHARE_READ OR FILE_SHARE_WRITE OR FILE_SHARE_DELETE,  nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

if (MoveParams.FileHandle = INVALID_HANDLE_VALUE) then
   MoveParams.FileHandle := CreateFile(PAnsiChar(AFile.FileName), GENERIC_READ,
     FILE_SHARE_READ OR FILE_SHARE_WRITE OR FILE_SHARE_DELETE,
     nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);
....

while WaitForSingleObject(MoveParams.FileHandle, 10) = 0 do
         begin
           AResult := DeviceIoControl(Volume.Handle, FSCTL_MOVE_FILE, @MoveParams,
             sizeof(MoveParams), nil, 0, w, @lSync);

           if Terminated then
           begin
             CancelIo(MoveParams.FileHandle);
             Break;
           end;
         end;

То что выделено жирным, это так было(вместо @lSync был nil). Все работало, но нельзя было остановить. Где я чего не так сделал?


 
Сергей М. ©   (2006-04-27 12:54) [3]

try
AResult := DeviceIoControl(Volume.Handle, FSCTL_MOVE_FILE, @MoveParams,
            sizeof(MoveParams), nil, 0, w, @lSync);
Win32Check(AResult);
try
while not Terminated do and (WaitForSingleObject(lSync.hEvent, 10) <> WAIT_OBJECT_0) do;
finally
CanselIO(MoveParams.FileHandle);
end;
except
..
end;


 
Игорь Шевченко ©   (2006-04-27 12:57) [4]


> Где я чего не так сделал?


Как минимум, не проверил состояние операции. Кроме того, при асинхронной операции управление в программу возвращается сразу после вызова DeviceIoControl, после него нужен WaitForMultipleObjects, где один из объектов - это событие асинхронного ввода-вывода (Overlapped.hEvent), а другой - это событие на завершение потока, внешнее.


 
Sally   (2006-04-27 13:51) [5]

>это событие на завершение потока
А это что?


 
Polevi ©   (2006-04-27 13:57) [6]

это некий объект при сигнале которого поточная ф-ия завершает свою работу
переводить этот объект в сигнальное состояние должен ты когда пожелаешь "остановить выполнение потока"


 
Sally   (2006-04-27 14:44) [7]

а где про все это можно прочитать подробно желательно с примерами?


 
Сергей М. ©   (2006-04-27 15:21) [8]


> Sally   (27.04.06 14:44) [7]


msdn.microsoft.com


 
Игорь Шевченко ©   (2006-04-27 15:37) [9]


> а где про все это можно прочитать подробно желательно с
> примерами?


Джеффри Рихтер, программирование для Win32


 
sally   (2006-04-27 18:50) [10]

сделал следующее:
private
 DeviceIoSync: OVERLAPPED;
 ThreadSync: OVERLAPPED;
 .....
public
 procedure StopThread;

procedure TThread1.StopThread;
begin
  SetEvent(ThreadSync.hEvent);
 Self.Terminate;
end;

constructor ....
FillChar(DeviceIoSync, SizeOf(TOverlapped), 0);
FillChar(ThreadSync, SizeOf(TOverlapped), 0);
DeviceIoSync.hEvent := CreateEvent(nil, true, FALSE, #0);
ThreadSync.hEvent := CreateEvent(nil, true, FALSE, #0);
....

Handles[0] := DeviceIoSync.hEvent;
Handles[1] := ThreadSync.hEvent;
....
AResult := DeviceIoControl(Volume.Handle, FSCTL_MOVE_FILE, @MoveParams, sizeof(MoveParams), nil, 0, w, @DeviceIoSync);
Win32Check(AResult);
AReason := WaitForMultipleObjects(2, @Handles, False, INFINITE);
   case AReason of
     WAIT_OBJECT_0: Result := mfrSuccess;
     WAIT_OBJECT_0 + 1, WAIT_ABANDONED_0 + 1, WAIT_ABANDONED_0:    CancelIO(MoveParams.FileHandle);
   end;;
Не выходит из DeviceIoControl....


 
Игорь Шевченко ©   (2006-04-27 18:59) [11]


> Не выходит из DeviceIoControl....


???? Как не выходит


 
Sally   (2006-04-27 19:00) [12]

Сорри...
Не выходит из
AReason := WaitForMultipleObjects(2, @Handles, False, INFINITE);


 
Sally   (2006-04-27 19:00) [13]

В догонку.... В смысле не останавливает процесс перемещения файла.


 
Игорь Шевченко ©   (2006-04-27 19:01) [14]

http://www.sysinternals.com/Information/DiskDefragmenting.html


 
Игорь Шевченко ©   (2006-04-27 19:02) [15]


> В догонку.... В смысле не останавливает процесс перемещения
> файла.


А как ты себе представляешь остановку процесса перемещения файла ? Половина кластеров переместилась, а половина на старом месте ?


 
Sally   (2006-04-27 19:06) [16]

Ну это я не придумал, просто дефрагментаторы при остановке дефрагментации не ждут окончания переноса файла. Большие файлы соответственно долго переносятся. Так вот если остановить процесс во время дефрагментации этого файла он остается на месте и не дефрагментируется.


 
Игорь Шевченко ©   (2006-04-27 19:10) [17]

Sally   (27.04.06 19:06) [16]

А по ссылке ничего не подходит ?


 
Sally   (2006-04-27 19:18) [18]

Не, там ничего такого нет...


 
Sally   (2006-04-27 19:23) [19]

А может быть дело в INFINITE?


 
Sally   (2006-04-27 19:39) [20]

AResult := DeviceIoControl(Volume.Handle, FSCTL_MOVE_FILE, @MoveParams, sizeof(MoveParams), nil, 0, w, @DeviceIoSync);
Не выходит именно из этой операции!!!


 
Сергей М. ©   (2006-04-28 08:54) [21]


> Не выходит именно из этой операции


Быть того не может.

Цитата из справки к DeviceIoControl:

If hDevice was opened with the FILE_FLAG_OVERLAPPED flag, this parameter must point to a valid OVERLAPPED structure. In this case, DeviceIoControl is performed as an overlapped (asynchronous) operation. If the device was opened with FILE_FLAG_OVERLAPPED and lpOverlapped is NULL, the function fails in unpredictable ways.
If hDevice was opened without specifying the FILE_FLAG_OVERLAPPED flag, this parameter is ignored and the DeviceIoControl function does not return until the operation has been completed, or an error occurs.


 
sally   (2006-04-28 10:17) [22]

>Сергей М
Я тоже умею пользоваться Ctrl+C и Ctrl+V
>Быть того не может.
Это из цикла:
-Ты суслика видишь.
-Нет.
-И я нет, а он есть

Функция ожидает окончания процесса перемещения.

DeviceHandle := CreateFile(PAnsiChar(UnNormilizeDrive(DriveName)), GENERIC_READ,
   FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
   nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

Так "создается" девайс.

в [10] все далее.


 
Сергей М. ©   (2006-04-28 10:41) [23]


> sally   (28.04.06 10:17) [22]


А останов треда по Program Pause при этом нормально происходит ?

Я к тому что здесь всего два варианта : либо overlapped-режим не задействован, либо при вызове DeviceIoControl происходит исключение.


 
Игорь Шевченко ©   (2006-04-28 11:02) [24]

Какой результат возвращает DeviceIoControl после начала операции ?


 
Sally   (2006-04-28 11:02) [25]

>А останов треда по Program Pause при этом нормально происходит
Это что такое?
В смысле, если Thread.Terminate или Thread.Suspend сдедать?
Нормально... Т.е. DeviceIoControl продолжает выполнение операции :) Вот когда он закончит, тогда Thread и дестроится.
Почему-то не включается overlapped режим...


 
Сергей М. ©   (2006-04-28 11:13) [26]


> Это что такое?


Это меню Run -> Program Pause


 
Игорь Шевченко ©   (2006-04-28 11:13) [27]

При начале асинхронной операции функция GetLastError должна возращать ERROR_IO_PENDING (997)


 
Sally   (2006-04-28 11:24) [28]

>Какой результат возвращает DeviceIoControl после начала операции
DeviceIoControl ждет окончания операции. Он ничего не возвращает.
Повотрюсь, скорее всего не включается overlapped режим...


 
Сергей М. ©   (2006-04-28 11:47) [29]

Попробуй использовать NtFsControlFile вместо DeviceIoControl.

Кстати, ты ОС не обозначил, скорей всего есть какие-то системозависимые ограничения в этой части.


 
sally   (2006-04-28 12:05) [30]

Прикольно, но ни в MSDN ни на сайте msdn.microsoft.com ничего про эту функцию нет...
Попробуем...


 
sally   (2006-04-28 15:22) [31]

Дааа... А может кто видел реализацию NTDDK.H для Delphi


 
Игорь Шевченко ©   (2006-04-28 15:26) [32]


> ... А может кто видел реализацию NTDDK.H для Delphi


на www.delphi-jedi.org поищи
еще здесь кое-что: http://kladovka.net.ru/download.cgi?id=48


 
Sally   (2006-04-28 15:29) [33]

То что нужно. Спасибо


 
Sally   (2006-04-28 16:09) [34]

Скажите, этот высов правильный, для того, чтобы установить OVERLAPPED режим?
DeviceHandle := CreateFile(PAnsiChar(UnNormilizeDrive(DriveName)), GENERIC_READ,
  FILE_SHARE_READ or FILE_SHARE_WRITE or FILE_SHARE_DELETE,
  nil, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, 0);

function UnNormilizeDrive(const ADrivePath: string): string;
begin
 Result := "//./" + Copy(ADrivePath, 1, Pos("\", ADrivePath) - 1)
end;

Потому что и с NtFsControlFile ничего не получается.


 
Игорь Шевченко ©   (2006-04-28 16:13) [35]

Sally   (28.04.06 16:09) [34]

Я бы, как минимум, добавил GENERIC_WRITE, так как операции по перемещению файла по идее требуют доступ на запись.

Я бы, как минимум, вставил бы просто имя диска, соответственно требованиям CreateFile, для исключения остальных проблем на данном этапе.

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


 
Сергей М. ©   (2006-04-28 16:18) [36]

Если DeviceHandle = True, то вызов правильный.

Но я бы добавил к FILE_FLAG_OVERLAPPED флаг FILE_FLAG_NO_BUFFERING.


 
Sally   (2006-04-28 16:26) [37]

Ничего тогда не понимаю...
status := NtFsControlFile(Volume.Handle, DeviceIoSync.hEvent, nil, nil, @ioStatus, FSCTL_MOVE_FILE, @MoveParams, sizeof(MoveParams), nil, 0);
   if ( status = STATUS_PENDING ) then
   begin
   WaitForSingleObject(MoveParams.FileHandle, INFINITE);
     status := ioStatus.Status;
   end;

Ниразу он внутрь if не заходит.


 
Игорь Шевченко ©   (2006-04-28 16:44) [38]

Sally   (28.04.06 16:26) [37]

А чему равен Status ?


 
Sally   (2006-04-28 16:49) [39]

Status=0


 
Сергей М. ©   (2006-04-28 16:54) [40]

http://www.sysinternals.com/Information/DiskDefragmenting.html

Это читал ?



Страницы: 1 2 вся ветка

Текущий архив: 2006.08.20;
Скачать: CL | DM;

Наверх




Память: 0.56 MB
Время: 0.069 c
15-1153472316
Strate
2006-07-21 12:58
2006.08.20
Тест браузеров


2-1154520955
Grant
2006-08-02 16:15
2006.08.20
Денежный разделитель


2-1154348555
Neket
2006-07-31 16:22
2006.08.20
IdSNMP1


3-1150371269
Vital_k
2006-06-15 15:34
2006.08.20
Картинка в базе


2-1154591813
TRyaSS
2006-08-03 11:56
2006.08.20
Почему FindFirstFile ищет только в текущем каталоге