Qwertiy писал(а):А нельзя как-то убить поток (вместе с TFileStream) и создать новый (т. е. в каждом новом потоке новый TFileStream)?
Насколько мне известно, я так и сделал... но завершение потока (Terminate) судя по всему встает в очередь и виснет в ожидании (или же поток остается активным до момента пока не подойдет очередь услышать что ему отправлена команда Terminate).
killfactory писал(а):Не совсем в пределах топика, но Windows API при асинхронной работе с файлами предлагает операцию CancelIO
Конечно, для использования этих механизмов придется отказаться от использования tFileStream, но, возможно, это тот самый путь, который позволит прервать чтение сбойного кластера на CD, не дожидаясь окончания этого процесса обычным путем. Проверить сейчас, к сожалению, нет возможности.
С одной стороны я потому и упомянул об использовании TFileStream, что у меня функция копирования построена на его основе (а это вероятно самая большая функция в программе и мысль о взбирании на эверест у меня вызывает меньше страха чем мысль о значительном перестраивании этой функции), но с другой стороны вероятно есть способы использовать предложенный вариант лишь в случаях наличия нечитаемых фрагментов. Впрочем в моей реализации проверочный фрагмент кода с ReadFileEx/CancelIo почему-то желаемого результата не дает: если делать без потоков то на сбойном фрагменте вся программа подвисает и соответственно не удается даже получить с семафора сигнал о том что 5-ть секунд истекли, если же сделать с потоком и при попытках чтения сбойного фрагмента попытаться "вручную" (с кнопки на форме) выполнить CancelIo по отношению к хэндлу мучаемого в потоке файла, то ничего позитивного не происходит и программа, даже будучи уже закрытой, "удерживает" файл и "отпускает" его лишь при нажатии кнопки выброса диска на приводе. Вот фрагмент кода, о котором идет речь:
Код: Выделить всё
static void CALLBACK FileIOComplete(DWORD dwError, DWORD dwBytes, LPOVERLAPPED ovl)
{
// не используется
}
//---------------------------------------------------------------------------
void __fastcall TForm1::Button1Click(TObject *Sender)
{
HANDLE hSem = CreateSemaphoreW(NULL, 1, 1, NULL);
LPVOID lpBuffer = HeapAlloc(GetProcessHeap(), 0, 4096);
OVERLAPPED ovl;
ovl.Offset = 264809910; // место в файле, с которого начинаются нечитаемые блоки
ovl.OffsetHigh = 0;
ovl.hEvent = hSem;
HANDLE hDataf = CreateFileW(L"n:\\badfile.dat", GENERIC_READ, 0, NULL, OPEN_EXISTING, FILE_FLAG_WRITE_THROUGH, 0);
while (true)
{
ReleaseSemaphore(ovl.hEvent, 1, NULL);
ReadFileEx(hDataf, lpBuffer, 4096, &ovl, FileIOComplete);
int s_res=WaitForSingleObjectEx(hSem, 5000, false);
while (s_res==WAIT_IO_COMPLETION)
{
s_res=WaitForSingleObjectEx(hSem, 5000, false);
}
if (s_res==WAIT_TIMEOUT)
{
CancelIo(hDataf);
}
ovl.Offset += 4096;
}
CloseHandle(ovl.hEvent);
}
//---------------------------------------------------------------------------
Должен признать что с ассинхронным чтением файла мне пока что сталкиваться не доводилось, а потому я не особо понимаю специфику процесса, в связи с чем в этом коде скорее всего есть некоторое количество некорректных действий. Если Вам удастся исправить этот код до рабочего состояния (или если предоставите собственный вариант работающего в этом направлении кода), то я буду весьма признателен. [/color]