Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
6-1156147512
pvi
2006-08-21 12:05
2007.01.21
Ограничение mailto на тело письма


15-1167746171
lookin
2007-01-02 16:56
2007.01.21
Любителям английского


6-1155728885
vodvorezlaya
2006-08-16 15:48
2007.01.21
докачка файлов из сети


15-1167689053
ProgRAMmer Dimonych
2007-01-02 01:04
2007.01.21
Объясните мне тупому...


2-1167822644
Влад
2007-01-03 14:10
2007.01.21
длина строки





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский