Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "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.062 c
15-1270622334
Мимо не прошел
2010-04-07 10:38
2010.08.27
отделить шум от голоса в мп3 подручными средствами


2-1267790032
Sairex
2010-03-05 14:53
2010.08.27
Как обойти подводный Камень приведения к типу


15-1264596540
dars73
2010-01-27 15:49
2010.08.27
SQL Возможно ли?


2-1272931604
Delphist2
2010-05-04 04:06
2010.08.27
передача управления


15-1272339322
Девелопер
2010-04-27 07:35
2010.08.27
Свойства бинарника и директивы компилятора





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский