Форум: "Основная";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];
ВнизТеоритический вопрос про потоки и контекст Найти похожие ветки
← →
guav © (2006-11-24 12:44) [40]> На время выполнения TThead.Create в последних весриях Delphi
> новый (создаваемый) поток вообще спит.
... а в не-последних делают так (привожу не псевдокод, а код, и Вы тоже код приводите, его читать легче, а то [2])constructor TMyThead.Create;
Begin
inherited Create(True); // создаём остановленным
SL := TStringList.Create;
...
Resume; // вот тут он пробуждается.
end;
Вроде даже в справке это разжевано...
← →
guav © (2006-11-24 12:56) [41]> [30] Anatoly Podgoretsky © (23.11.06 17:06)
> Автор утверждает, что первостепенным явлется в контексте
> какого потока создается, а не в контексте какого используется.
"сама переменная" создаётся для всего процесса, даже если она создаётся в стеке потока (имеется ввиду "настоящая" переменная, а не threadvar). Т.е. потоки ей пофиг.
Выделение памяти под указатель сделано потокобезопасным и может осуществлятся из любого потока, в самой RTL есть пример выделения в одном потоке и совобождения в другом.
А вот для кода может быть и не всё равно, ему смена контекста может повредить, если там использован например GetCurrentThreadId для заполнения поля класса. Т.е. контекст вызова конструктора может играть роль.
← →
Anatoly Podgoretsky © (2006-11-24 13:06) [42]> guav (24.11.2006 12:44:40) [40]
Именно так у меня и сделано, возможно только что сетевые компоненты так нельзя создавать, возможно они что то внутри делают с текущим потоком, тоже для базы.
Автор утверждает, что и создание и сама переменная должны находиться в методе Execute. Более того упирает на слово сама переменная, а не создание или использование.
Именно это меня и смущает. Но я в текущей ситуации уже не могут так, поскольку есть много других методов, ну не передавать же мне туда переменную? А их не одна. Есть модуль данных, есть сетевые компоненты, есть компоненты БД и другие переменные, которые должны быть доступны и в главном потоке. Ну ладно я переместил сетевые компоненты и компоненты БД в модуль данных и если будут проблемы, то буду передавать ссылку на модуль данных.
Мне бы было проще и удобнее, если бы я мог объявить все в секции private, не беспокоясь об их уничтожение и доступности.
Я сейчас не могу проверить технически, поскольку идет полная переделка структуры и поиск оптимального варианта. Через несколько дней я смогу подойти к трассировке.
Повторяю еще раз мысль автора - не важно где создается, важно только где объявлено. Вот этому утверждению и ищу какое либо подтверждение, поскольку все остальные, включая меня говорять обратное, логика то простая.
Более того его утверждение нашло физическое подтверждение, перенос переменной сняло вопрос.
← →
Slym_RO (2006-11-24 13:19) [43]2,3 - в контексте потока, накакать где хранится ссылка на обект
1 - сложнее:
1.1. в контексте потокаconstructor TT.Create;
begin
inherited Create(True);
SL := TStringList.Create;
Resume;
end;
1.1. в контексте ОСНОВНОГО потокаconstructor TT.Create;
begin
SL := TStringList.Create;
inherited Create(True);
Resume;
end;
← →
Slym_RO (2006-11-24 13:20) [44]Ганю! 1 всегда в контексте ОСНОВНОГО потока
← →
Sly_RO (2006-11-24 13:33) [45]Delphi 7
function ThreadProc(Thread: TThread): Integer;
var
FreeThread: Boolean;
begin
{$IFDEF LINUX}
if Thread.FSuspended then sem_wait(Thread.FCreateSuspendedSem);
{$ENDIF}
try
if not Thread.Terminated then
try
Thread.Execute;
except
Thread.FFatalException := AcquireExceptionObject;
end;
finally
FreeThread := Thread.FFreeOnTerminate;
Result := Thread.FReturnValue;
Thread.DoTerminate;
Thread.FFinished := True;
SignalSyncEvent;
if FreeThread then Thread.Free;
{$IFDEF MSWINDOWS}
EndThread(Result);
{$ENDIF}
{$IFDEF LINUX}
// Directly call pthread_exit since EndThread will detach the thread causing
// the pthread_join in TThread.WaitFor to fail. Also, make sure the EndThreadProc
// is called just like EndThread would do. EndThreadProc should not return
// and call pthread_exit itself.
if Assigned(EndThreadProc) then
EndThreadProc(Result);
pthread_exit(Pointer(Result));
{$ENDIF}
end;
end;
контекст созданного потока действует только в
Thread.Execute;
Thread.Free; при FreeOnTerminate=true
Thread.OnTerminate; - работает через Synchronize
← →
Anatoly Podgoretsky © (2006-11-24 13:45) [46]> guav (24.11.2006 12:56:41) [41]
Вот за это и боюсь
> если там использован например GetCurrentThreadId для заполнения поля класса.
Правда автор напирает на место объявления, это он подчеркнул не один раз.
Я не проверял вариант 2, когда объявление в private и создание в методе Execute, сразу перешел к методу 3, когда и объявление в методе Execute и создание объекта в нем же.
Потоки у меня никак не общаются с главном потоком, только создание и присвоение некоторых локальных простых переменных делается в главном потоке, потом запуск и в обработчике OnTerminate, который также выполняется в контексте главного потока.
Поэтому ни каких синхронизаций и возможных проблем из-за этого просто нет.
← →
guav © (2006-11-24 13:52) [47]> Более того его утверждение нашло физическое подтверждение,
> перенос переменной сняло вопрос.
Если перенос конструктора снял вопрос, то это можно понять (может они внутри, напимер, TLS используют), но место объявления переменной должно быть безразлично.
> Правда автор напирает на место объявления, это он подчеркнул
> не один раз.
Думаю зря, переменные принадлежат всему процессу.
← →
Anatoly Podgoretsky © (2006-11-24 13:52) [48]> Slym_RO (24.11.2006 13:19:43) [43]
У меня первый вариант (я учел возможности подобного), только одно замечание конструктор Create всегда выполняется к контексте главного потока.
и Resume у меня выполняется из главного потока, но это не существественно.
Автор утверждает, что обращения к SL будут выполняться в контексте главного потока, а не TT
Мне кажется он ошибается, возможно проблемы в его компоненте, в его внутренней структуре. Но факт остается фактом, перенос определения SL и соответственно Create в Execute решает проблему. Вместо SL можно подставить что угодно, SL только для примера. У меня как я говорил три класса динамических объектов - списки, Интернет компоненты и БД
Я тогда на более ранней стадии не стал разбираться и проверять все три варианта, но сейчас настал момент когда надо поставить точку в этом вопросе.
← →
Anatoly Podgoretsky © (2006-11-24 13:53) [49]> Slym_RO (24.11.2006 13:20:44) [44]
Пардон, это прочитал после отсылки ответа. Просто не обращай тогда на это замечания внимания.
← →
Alexander Panov © (2006-11-24 17:38) [50]Не так давно была веточка, в которой некоторые спецы утверждали, что поведение объекта не зависит от того, в основном потоке он создан, или в дополнительном.
Хотелось бы их послушать.
← →
Джо © (2006-11-24 18:07) [51]> [50] Alexander Panov © (24.11.06 17:38)
> Не так давно была веточка, в которой некоторые спецы утверждали,
> что поведение объекта не зависит от того, в основном потоке
> он создан, или в дополнительном.
Так дело-то вовсе не в том, в каком потоке он создан. Дело в самой логике работы конкретного объекта.
← →
Anatoly Podgoretsky © (2006-11-24 18:35) [52]Потому и завел ветку, что хочу подобное услышать, поскольку мнения разные.
← →
Anatoly Podgoretsky © (2006-11-24 18:54) [53]> Anatoly Podgoretsky (24.11.2006 18:35:52) [52]
Я нашел первый ответ автора в архиве его конференции
Your HTTP component runs in the main thread since you created in the context
of the main thread (TThread constructor execute in the context of the
calling thread, not in the context of the created thread). Create you HTTP
component instance from the thread"s Execute method and free it at the end
of the Execute method.
← →
Anatoly Podgoretsky © (2006-11-24 18:56) [54]> Anatoly Podgoretsky (24.11.2006 18:35:52) [52]
Я сейчас приведу значимую переписку
Arno Garrels:
Component events are executed in worker thread context ONLY IF they
are either created in the Execute procedure or if you use methods
ThreadDetach/ThreadAttach instead. The hidden window of a ICS
component must be created in worker thread context.
TThread.Create is executed in the calling thread.
← →
Anatoly Podgoretsky © (2006-11-24 18:59) [55]> Anatoly Podgoretsky (24.11.2006 18:56:54) [54]
Francois Piette:
There is another issue you seems to ignore. A thread context is not related
at all to the TThread class. It is not because you run a TThread method that
it runs within the conext of the thread created by the TThread class !
A method is executed in the context of a thread only if it is called from
the Execute method (or any method called directly or indirectly by that
execute method). You can have any thread calling any method in a TThread
class instance but then the method is executed within the context of the
CALLING thread, not the context of the thread created by the class.
Speaking ICS components and events, the events are executed in the thread
context which CREATED the component (or the thread attached using
ThreadAttach method). No matter where the event handler is defined. This is
how Windows works.
← →
Eraser © (2006-11-24 19:11) [56]> [55] Anatoly Podgoretsky © (24.11.06 18:59)
> Speaking ICS components and events, the events are executed
> in the thread
> context which CREATED the component (or the thread attached
> using
> ThreadAttach method). No matter where the event handler
> is defined. This is
> how Windows works.
ну вот это много проясняет.. вот и событийное программирование..
тут как раз таки автор говорит, что события возникают в том потоке, в котором компонент был создан, ума не приложу где в доп. потоке будут вызываться асинхронные события, если там нету очереди обработки сообщений.
надо глянуть исходники ICS..
← →
Anatoly Podgoretsky © (2006-11-24 19:12) [57]> Anatoly Podgoretsky (24.11.2006 18:59:55) [55]
Ключевой фразой наверно будет эта
Speaking ICS components and events, the events are executed in the thread context which CREATED the component
То есть я могу объявить переменную в классе, но создовать объекты я должен только в методе Execute
Mythread = thread
HttpCli: THttpCli;
AdoDataset: TAdoDataset;
ThreadDataModule: TDataModule;
...
end;
И далее так
procedure MyUnit.Execute;
begin
HttpCli := THttpCli.Create();
ThreadDataModule := TAdoDataset.Create();
AdoDataset := TDataModule.Create();
...
end;
На этот раз мои мысли правильные?
Проблем не будет?
Планирую все динамические классы переместить в ThreadDataModule
У меня сейчас почти так, только переменные этого типа локальные в Execute, тут никаких проблем пока обнаружить не удалось. Я каждый вечер запускаю программу под отладчиком и во всех блоках except end установлена точка останова. Попадаю туда только по физическим проблемам, типа таймаут соединения с форумами или счетчиком top.list.ru и также при попытке получить удаленую запись. Больше никаких ошибок.
Надо было давно перечитать то обсуждение. Кое что забыл и переврал :-)
← →
Anatoly Podgoretsky © (2006-11-24 19:18) [58]> Eraser (24.11.2006 19:11:56) [56]
Очередь сообщений я вырезал из сообщения.
← →
Eraser © (2006-11-24 19:18) [59]видимо собака порылась тут )
procedure TIcsWndControl.AllocateHWnd;
begin
if FHandle <> 0 then
Exit; // Already done
FThreadId := GetCurrentThreadId;
GWndHandlerPool.Lock;
try
if not Assigned(FWndHandler) then
FWndHandler := GWndHandlerPool.GetWndHandler(MsgHandlersCount,
FThreadId);
FWndHandler.AllocateHWnd;
FHandle := FWndHandler.Handle;
AllocateMsgHandlers;
finally
GWndHandlerPool.UnLock;
end;
end;
← →
Anatoly Podgoretsky © (2006-11-24 19:31) [60]> Eraser (24.11.2006 19:18:59) [59]
Вероятно, если вызывать из Create то это будет контекст главного потока.
← →
Eraser © (2006-11-24 19:34) [61]> [60] Anatoly Podgoretsky © (24.11.06 19:31)
точнее не главного, а вызывающего.
← →
Anatoly Podgoretsky © (2006-11-24 19:56) [62]> Eraser (24.11.2006 19:34:01) [61]
У меня просто они равны. Вызывается из главного.
← →
guav © (2006-11-24 21:06) [63]> [59] Eraser © (24.11.06 19:18)
> FThreadId := GetCurrentThreadId;
гы, угадал (хотя это может быть и не едиснтвенное):
> [41] guav © (24.11.06 12:56)
> если там использован например GetCurrentThreadId
И зачем им он нужен ?
И кто отвечает за диспечеризацию сообщений окна ICS в доп потоке ?
> [57] Anatoly Podgoretsky © (24.11.06 19:12)
> На этот раз мои мысли правильные?
Думаю, да :-)
← →
Leonid Troyanovsky © (2006-11-25 12:48) [64]
> Eraser © (24.11.06 19:18) [59]
> видимо собака порылась тут )
Скорее всего, что не в подчеркнутом, а в FWndHandler.AllocateHWnd
Хотя, исходников не имею, а лишь догадываюсь, что имеется ввиду.
--
Regards, LVT.
Страницы: 1 2 вся ветка
Форум: "Основная";
Текущий архив: 2007.01.21;
Скачать: [xml.tar.bz2];
Память: 0.59 MB
Время: 0.045 c