![]() |
| ||
|
|
Новости |
Поиск |
FAQ |
Статьи |
Книги |
Новости VCL
| | Форумы ЧАТ |
Орешник |
|
| |||
| |||
« предыдущая ветвь | форум | следующая ветвь »
Теоритический вопрос про потоки и контекст
Anatoly Podgoretsky © (2006-11-23 14:28:00)Интересует следующая вещь, поскольку информация противоречивая.
Допустим есть следующий код, значимые куски
Thead = TThead
SL: TStringList
end;
TThead.Create;
Begin
SL := TStringList.Create;
end;
TThead.Execute;
Begin
SL := TStringList.Create;
end;
TThead.Execute;
var
SL: TStringList;
Begin
SL := TStringList.Create;
end;
В контексте какого потока будет выполняться следующий код, для каждого из трех вариантов, если Create вызывается в главном потоке?
TThead.Execute;
Begin
SL := SL[0]
end;
С третьем случае все одназначно, в контексте потока, а первые два?
Slym_RO (2006-11-24 13:20:00) [21]Ганю! 1 всегда в контексте ОСНОВНОГО потока
Slym_RO (2006-11-24 13:19:00) [22]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;
Anatoly Podgoretsky (2006-11-24 13:06:00) [23]> guav (24.11.2006 12:44:40) [40]
Именно так у меня и сделано, возможно только что сетевые компоненты так нельзя создавать, возможно они что то внутри делают с текущим потоком, тоже для базы.
Автор утверждает, что и создание и сама переменнаядолжны находиться в методе Execute. Более того упирает на слово сама переменная, а не создание или использование.
Именно это меня и смущает. Но я в текущей ситуации уже не могут так, поскольку есть много других методов, ну не передавать же мне туда переменную? А их не одна. Есть модуль данных, есть сетевые компоненты, есть компоненты БД и другие переменные, которые должны быть доступны и в главном потоке. Ну ладно я переместил сетевые компоненты и компоненты БД в модуль данных и если будут проблемы, то буду передавать ссылку на модуль данных.
Мне бы было проще и удобнее, если бы я мог объявить все в секции private, не беспокоясь об их уничтожение и доступности.
Я сейчас не могу проверить технически, поскольку идет полная переделка структуры и поиск оптимального варианта. Через несколько дней я смогу подойти к трассировке.
Повторяю еще раз мысль автора - не важно где создается, важно только где объявлено. Вот этому утверждению и ищу какое либо подтверждение, поскольку все остальные, включая меня говорять обратное, логика то простая.
Более того его утверждение нашло физическое подтверждение, перенос переменной сняло вопрос.
guav (2006-11-24 12:56:00) [24]> [30] Anatoly Podgoretsky © (23.11.06 17:06)
> Автор утверждает, что первостепенным явлется в контексте
> какого потока создается, а не в контексте какого используется.
"сама переменная" создаётся для всего процесса, даже если она создаётся в стеке потока (имеется ввиду "настоящая" переменная, а не threadvar). Т.е. потоки ей пофиг.
Выделение памяти под указатель сделано потокобезопасным и может осуществлятся из любого потока, в самой RTL есть пример выделения в одном потоке и совобождения в другом.
А вот для кода может быть и не всё равно, ему смена контекста может повредить, если там использован например GetCurrentThreadId для заполнения поля класса. Т.е. контекст вызова конструктора может играть роль.
guav (2006-11-24 12:44:00) [25]> На время выполнения TThead.Create в последних весриях Delphi
> новый (создаваемый) поток вообще спит.
... а в не-последних делают так (привожу не псевдокод, а код, и Вы тоже код приводите, его читать легче, а то [2])
constructor TMyThead.Create;
Begin
inherited Create(True); // создаём остановленным
SL := TStringList.Create;
...
Resume; // вот тут он пробуждается.
end;
Вроде даже в справке это разжевано...
guav (2006-11-24 12:40:00) [26]> [6] Anatoly Podgoretsky © (23.11.06 14:44)
> C третьим все ясно.
Со вторым тоже, тоже из создаваемого потока, ничем от второго не отличается.
Первый из создающего. На время выполнения TThead.Create в последних весриях Delphi новый (создаваемый) поток вообще спит.
Не верите, смотрите генофонд и вызывайте GetCurrentThreadId
Anatoly Podgoretsky (2006-11-23 18:23:00) [27]> Leonid Troyanovsky (23.11.2006 18:05:34) [34]
Чистый стринг лист, чистый HTTPCli, ну и ранее был Absolute Database - все они расчитаны на работу в потоках, сейчас перевожу на АДО
За счет переноса объявлений в Execute проблема была полностью решена. Но сейчас я хочу сильно пересмотреть структуру программы, применить индивидуальные модули данных для каждого потока и желательно его объявить и создавать в Thread.Create
На модуле данных будут лежать вышеуказаные компоненты.
Anatoly Podgoretsky (2006-11-23 18:17:00) [28]> Джо (23.11.2006 17:46:33) [33]
Конечно разберусь и даже потоки не требуются, я их применил, что бы быстро сделать приложение. Во втором рефакторинге наверно откажусь от них, надо только поработать.
Anatoly Podgoretsky (2006-11-23 18:16:00) [29]> Eraser (23.11.2006 17:19:31) [31]
AV это аргумент или нет?
Anatoly Podgoretsky (2006-11-23 18:14:00) [30]> Джо (23.11.2006 17:05:29) [29]
Это из почты, которую я ежедневно уничтожаю
Leonid Troyanovsky (2006-11-23 18:05:00) [31]
> Anatoly Podgoretsky © (23.11.06 14:28)
> SL: TStringList
Если речь идет о чистом TStringList, а не о неких потомках,
то место его создания значения не имеет.
Т.е., он, как раз, является примером thread-safe VCL.
Правда, анализировал исходники еще в D2.
Конечно, в случае с потомками, это легко опровергнуть.
--
Regards, LVT.
Джо (2006-11-23 17:46:00) [32]> [32] Romkin © (23.11.06 17:31)
> Конечно, не важно, где лежит указатель. Вот только
> кроме указателя есть куча вещей, которые зависят от потока
Насчет этого я (и не только я, кажется) уже говорил. Анатолий берет ответственность на себя, утверждая, что с этим он сам разберется :)
Romkin (2006-11-23 17:31:00) [33]Логика, логика... ADO, скорее всего, надо создавать в том потоке, в котором используешь: там интерфейсы СОМ. И не так просто передавать интерфейс между потоками ;)
TTimer нужно создавать в execute - там сообщение. Которое придет в тот поток, который зарегистрирован...
И тд. Конечно, не важно, где лежит указатель. Вот только кроме указателя есть куча вещей, которые зависят от потока
Eraser (2006-11-23 17:19:00) [34]> [30] Anatoly Podgoretsky © (23.11.06 17:06)
> Если посмотреть на вариант 1 и 2, то там находится не в
> Execute и главный Сreate выполняется в контексте главного
> потока.
правильно, но, к примеру для TStringList, как и для 99% компонетов это нормально.
> Второй вариант я создаю в Execute, но сама переменная создана
> в контексте главного потока. Автор утверждает
я тут вижу противоречие :)
> Моя логика с этим не соглашается.
> Поведение показывает, что моя логика неверная.
а можно пример, уж очень заинтриговали )
Anatoly Podgoretsky (2006-11-23 17:06:00) [35]> Eraser (23.11.2006 16:32:27) [27]
Если посмотреть на вариант 1 и 2, то там находится не в Execute и главный Сreate выполняется в контексте главного потока. Второй вариант я создаю в Execute, но сама переменная создана в контексте главного потока. Автор утверждает, что первостепенным явлется в контексте какого потока создается, а не в контексте какого используется.
Вот об этом и есть вопрос.
Моя логика с этим не соглашается.
Поведение показывает, что моя логика неверная.
Джо (2006-11-23 17:05:00) [36]> [28] Anatoly Podgoretsky © (23.11.06 17:03)
> > Джо (23.11.2006 16:29:26) [26]
>
> Я уже сказал, что моя логика протестует, автор утверждает
> обратное.
Анатолий, а не могли бы вы привести полную цитату, да еще и с контекстом? Возможно, неверный перевод, да мало ли что.
Anatoly Podgoretsky (2006-11-23 17:03:00) [37]> Джо (23.11.2006 16:29:26) [26]
Я уже сказал, что моя логика протестует, автор утверждает обратное. Подтверждения ни тому ни другому по этому вопросу мне не встречалось.
Вопрос я вроде четко поставил, что именно интересует и в каком контесте, допольнительные уточнения тоже сделал.
Eraser (2006-11-23 16:32:00) [38]> [24] Anatoly Podgoretsky © (23.11.06 16:25)
> Но меня интересует не практический вопрос, а теоритический
1. то что находится в ф-ции Execute по определению выполняется в доп. потоке. Вот и вся теория )
2. где вызывать конструктор? для TSringList могу ответить - все равно где.
а вот для сетевых или, что вероятнее БД компонентов разница може быть, но тут уж нужно смотреть реализацию самих компонентов.
Джо (2006-11-23 16:29:00) [39]Ну, тогда для начала, Анатолий, попробуйте теоретически показать, отчего бы этому коду выполняться в ином потоке? Ведь очевидно же (я допускаю, что ошибочно) считать, что, раз никаких телодвижений для переключения контекста не делается, то и само-собой ничего не произойдет.
Anatoly Podgoretsky (2006-11-23 16:25:00) [40]> Джо (23.11.2006 15:58:22) [22]
Вопрос начинается со слов Теоритический вопрос