Форум: "WinAPI";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
ВнизМожно ли передавать из одного потока в другой хендл открытого Найти похожие ветки
← →
EgorovAlex © (2009-02-24 15:32) [0]файла? Почему спрашиваю - есть код, который много лет работал под NT/2000/XP/2003, так же нормально работает под Vista и 7 beta, а вот под Server 2008 не работает - после того, как я передаю хендл в поток - операция чтения из этого хендла возвращает, что нет такого хендла :(
Что может быть?
← →
тимохов (2009-02-24 17:06) [1]что под потоком имеется в виду?
файл? хендл файла можно передавать.
и вообще - код приведи :)
← →
guav © (2009-02-24 23:10) [2]
> Что может быть?
Race condition :-)
← →
EgorovAlex © (2009-02-25 07:52) [3]Вот код:
procedure TestHandle(const hTest: Cardinal);
var
BytesRead: Cardinal;
Buf: array[0..102399] of Byte;
begin
SetFilePointer(hTest, 0, nil, FILE_BEGIN);
if not ReadFile(hTest, Buf, 1024, BytesRead, nil) then
MessageBox(0, PChar(SysErrorMessage(GetLastError)), "", MB_OK);
end;
type
TSaveThread = class(TThread)
hFile: Cardinal;
protected
constructor CreateIt(const hFile: Cardinal);
procedure Execute; override;
end;
constructor TSaveThread.CreateIt(const hFile: Cardinal);
begin
inherited Create(True);
TestHandle(hFile); // нормально
Self.hFile := hFile;
TestHandle(Self.hFile); // нормально
FreeOnTerminate := True;
Resume;
end;
procedure TSaveThread.Execute;
begin
TestHandle(hFile); // выдаёт Invalid File Handle
end;
← →
Palladin © (2009-02-25 08:34) [4]Это может произойти если ты сразу же, после создания потока, в основном закрыл handle.
← →
EgorovAlex © (2009-02-25 08:42) [5]Нет, закрытие у меня именно в потоке происходит, в основном коде закрытия нет, и ещё раз - этот код не работает только под Windows Server 2008, под всеми остальными осями работает :(
Я уже пару дней не могу разобраться, в VMWare все оси поставил для тестов
← →
Palladin © (2009-02-25 08:52) [6]У меня никакой ошибки не возникает. Ищи закрытие хендла в других местах.
← →
тимохов (2009-02-25 10:51) [7]Не знаю в этом ли ошибка, но так писать незя вообще (правда от версии Дельфи зависит - у них менялась реализация).
При этом я думаю, что ты неверно идентифицируешь ошибку, кстати.
Смотри, что происходит:
1. При вызове Resume начинает работать функция ThreadProc из classes.
2. Они быстро выполняет Execute.
3. Все это заканчивается тем, что еще до выхода из Createit поток уже закончил работу и уничтожен :)
Что делать? Написать вот так:constructor TSaveThread.CreateIt(const hFile: Cardinal);
begin
inherited Create(False);
TestHandle(hFile); // нормально
Self.hFile := hFile;
TestHandle(Self.hFile); // нормально
FreeOnTerminate := True;
end;
← →
тимохов (2009-02-25 10:53) [8]Пояснение - не делать поток suspended = true (см. параметр inherited Create).
Вообще, очень похоже, что я прав, т.к. в разных Windows, видимо, разные немного планировщики потоков (помню тут Piter долго возмущался, что крит. секция в висте не так работает). Вот и получается, что у тебя отдается приоритет проснувшемуся потоку.
← →
EgorovAlex © (2009-02-25 10:59) [9]А в приведённом коде не получится так, что после вызова
inherited Create(False);
метод Execute выполнится раньше, чем произойдёт инициализация данных?
← →
Palladin © (2009-02-25 11:05) [10]Нет, конструктор выполняется в основном потоке, Execute начинает выполнятся после Resume.
← →
Palladin © (2009-02-25 11:06) [11]
> EgorovAlex © (25.02.09 10:59) [9]
А, в этом случае да, конечно, после Inherited(False) Execute сразу пойдет на выполнение. Этого делать нельзя.
← →
Palladin © (2009-02-25 11:11) [12]
> тимохов (25.02.09 10:51) [7]
А если подумать получше? Ты написал все с точностью до наоборот.
← →
EgorovAlex © (2009-02-25 11:14) [13]После дополнительного тестирования получилось так - при удалённой отладке (remote debug) не работает, а без отладки работает... странно как-то вышло
← →
тимохов (2009-02-25 11:34) [14]
> Palladin © (25.02.09 11:11) [12]
>
>
> > тимохов (25.02.09 10:51) [7]
>
> А если подумать получше? Ты написал все с точностью до наоборот.
>
блин, ты исходники посмотри, а потом говори. ок?
обрати внимание на procedure TThread.AfterConstruction.
вообще я уверен, что проблема в чем я сказал :)
-----
это тонкое место, на нем ломались многие. мне первый раз на него обратил внимание Александр Шахнов (кажется). я тогда сам прибалдел немного. однако я прав. писать надо false в конструкторе, либо не пиисать FreeOnTerminate.
← →
тимохов (2009-02-25 11:41) [15]
> EgorovAlex © (25.02.09 10:59) [9]
>
> А в приведённом коде не получится так, что после вызова
>
> inherited Create(False);
>
> метод Execute выполнится раньше, чем произойдёт инициализация
> данных?
реально потом все равно создается отстновленным, а запускается в AfterConstruction.
Смотри исходники.
← →
Сергей М. © (2009-02-25 15:27) [16]
> EgorovAlex
Что ж ты так мучаешься ?)
Ну сделай ты дубликат хэндла и передай его конструируемому потоку, а оригинал смело удаляй..
← →
EgorovAlex © (2009-02-25 15:54) [17]У меня файл создаётся с флагом DELETE_ON_CLOSE, если я создам дубликат, а оригинальный хендл закрою, это нормально пройдёт, файл не удалится?
И ещё, как правильно сделать дубликат, там что-то очень много параметров у функции
← →
Сергей М. © (2009-02-25 15:56) [18]
> EgorovAlex © (25.02.09 15:54) [17]
FILE_FLAG_DELETE_ON_CLOSE
Indicates that the operating system is to delete the file immediately after all of its handles have been closed, not just the handle for which you specified FILE_FLAG_DELETE_ON_CLOSE.
> что-то очень много параметров у функции
Что не понятно ?
← →
EgorovAlex © (2009-02-25 16:15) [19]Примерно так:? или вместо GetCurrentProcess лучше GetCurrentThread?
DuplicateHandle(GetCurrentProcess, hFile, GetCurrentProcess, @hDup, 0, True, DUPLICATE_SAME_ACCESS);
← →
тимохов (2009-02-25 16:23) [20]2Автор.
Ты попробовал сделать что я тебе сказал?
У тебя в коде потенциальная ошибка 100%.
Даже если не она причина, все равно поправь.
← →
EgorovAlex © (2009-02-25 16:26) [21]2тимохов
пробовал - результат тот-же, но Execute действительно начинает работать после выхода из моего конструктора
← →
Сергей М. © (2009-02-25 16:36) [22]
> или вместо GetCurrentProcess лучше GetCurrentThread?
Нет, именно GetCurrentProcess
← →
тимохов (2009-02-25 16:46) [23]
> EgorovAlex © (25.02.09 16:26) [21]
>
> 2тимохов
> пробовал - результат тот-же, но Execute действительно начинает
> работать после выхода из моего конструктора
Он может закончится до конца конструктора :)
Мне лень писать пример. Ну, хотя бы сделай sleep после resume в твоем варианте на 5 сек., увидишь, что execute успеет отработать, соответственно к концу Create объекта уже нет :)
скорее всего это вряд ли причина именно твоей ошибки, но это точно источник потенциальных ошибок. причем трудно выводимых.
надо, конечно, немного подумать, чтобы ошибку гарантировано получить, но в твоем случае класс потома может быть уничтожен до выполнения, скажем TThread.AfterConstruction, где есть обращения к членам класса, а если объект уничтожен, то потенциально может быть AV.
← →
Leonid Troyanovsky © (2009-02-25 18:38) [24]
> EgorovAlex © (25.02.09 07:52) [3]
> if not ReadFile(hTest, Buf, 1024, BytesRead, nil) then
Buf[0]
И чего он такого размера, если читают всего ничего?
--
Regards, LVT.
← →
Германн © (2009-02-25 18:46) [25]
> Leonid Troyanovsky © (25.02.09 18:38) [24]
> Buf[0]
Почему?
← →
Leonid Troyanovsky © (2009-02-25 18:57) [26]
> Германн © (25.02.09 18:46) [25]
> Почему?
Видимо, паранойя :)
--
Regards, LVT.
← →
Германн © (2009-02-26 00:54) [27]
> Leonid Troyanovsky © (25.02.09 18:57) [26]
>
>
> > Германн © (25.02.09 18:46) [25]
>
> > Почему?
>
> Видимо, паранойя :)
А ну да. Пиши всегда [0] и на все случаи застрахован! То бишь главное "не политурить" (с) Р. Шекли.
:)
> И чего он такого размера, если читают всего ничего?
>
Видимо шизофрения :)
Или какой-то подвид нумерологии. Ибо я не могу никак понять смысл чисел
102399 и 102400!
Страницы: 1 вся ветка
Форум: "WinAPI";
Текущий архив: 2010.08.27;
Скачать: [xml.tar.bz2];
Память: 0.51 MB
Время: 0.063 c