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

Вниз

Можно ли передавать из одного потока в другой хендл открытого   Найти похожие ветки 

 
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 вся ветка

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

Наверх




Память: 0.54 MB
Время: 0.124 c
2-1275629647
Delphist2
2010-06-04 09:34
2010.08.27
Как в winapi различить 2 контрола одного класса на окне?


2-1267779863
Цукор5
2010-03-05 12:04
2010.08.27
ambiguous overloaded call GetFactoryNumber


15-1265044912
xayam
2010-02-01 20:21
2010.08.27
Тест на сообразительность


15-1269273636
Правильный$Вася
2010-03-22 19:00
2010.08.27
многосессионный диск - копирование образа


15-1274167672
ixen
2010-05-18 11:27
2010.08.27
Ошибка при подключении к RDP через UserGate 5