Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 08.08.2012, 03:08   #1
Базиля
Участник клуба
 
Аватар для Базиля
 
Регистрация: 03.12.2009
Сообщений: 1,013
Смущение Потоки

Доброй - доброй ночи
Если обращаться в потоке напрямую к какому - либо компоненту, то периодически будет вылазить ошибка "Canvas does not allow drawing".
Правильно ли я понимаю причину данной ошибки - произошла такая ситуация, именно в этот момент главный поток мог обращаться к компоненту, поправьте пожалуйста если я не прав.
Synchronize исправляет данную проблему (тем самым мы передаем обращение к компоненту главному потоку, тем самым не позволим в случае чего обращаться нашему потоку к компоненту)
Вызываю данную процедурку и в качестве параметра указываю имя процедуры в которой собственно и буду производить нужные изменения с компонентом.
Но вот возникает сразу же такой вопрос, будет ли считаться обращением к компоненту, если я хочу получить значение какого - либо свойства?
Могу ли я это делать напрямую из своего потока? Или опять таки нужно применять синхронизацию?
P.S. Прошу прощения за такие вопросы, но в моей голове пока что царит туманище по данному вопросу

Последний раз редактировалось Базиля; 08.08.2012 в 03:11.
Базиля вне форума Ответить с цитированием
Старый 08.08.2012, 07:04   #2
GunSmoker
Старожил
 
Регистрация: 13.08.2009
Сообщений: 2,581
По умолчанию

Сильно зависит от реализации свойства, которое ты читаешь. Лучше перестраховаться и выполнять синхронизацию.

Вообще, лучшая синхронизация - это та, которую не нужно выполнять. Твоему потоку нужны какие-то данные для работы? Собери их в кучу до запуска потока и передай потоку параметрами по значению (с копированием). Тогда в потоке будет копия всех необходимых данных, к которой можно обращаться в любой момент без необходимости синхронизации.

Если параметры изменяются во время работы потока и потоку нужно знать их актуальное значение, то такой способ не подойдёт. В этом случае лучше всего завести отдельное хранилище переменных (запись или класс с методами Lock/Unlock). В поток передать это хранилище по ссылке (без копирования). Когда потоку нужны значения - он делает Lock, читает параметр, делает Unlock. Когда параметр изменяется (не важно в каком потоке), его значение нужно обновить и в хранилище. Делаем Lock, обновляем, Unlock.
Опытный программист на C++ легко решает любые не существующие в Паскале проблемы.
GunSmoker вне форума Ответить с цитированием
Старый 08.08.2012, 13:02   #3
Базиля
Участник клуба
 
Аватар для Базиля
 
Регистрация: 03.12.2009
Сообщений: 1,013
По умолчанию

GunSmoker
Спасибо за разъяснение! Буду разбираться.
Цитата:
Сильно зависит от реализации свойства, которое ты читаешь.
Ну как пример, забираю количество строк в мемо или же какую-либо строку.

А вот как тогда быть если я хочу в потоке добавлять запись в БД, т.е. идет обращение к adoquery или же он не относится к VCL и можно смело к нему обращаться?
Базиля вне форума Ответить с цитированием
Старый 08.08.2012, 13:16   #4
Аватар
Старожил
 
Аватар для Аватар
 
Регистрация: 17.11.2010
Сообщений: 18,922
По умолчанию

Цитата:
он не относится к VCL и можно смело к нему обращаться
Не пойдет. То же, что GunSmoker предложил - Lock и Unlock по выходу из блока обновления
Если бы архитекторы строили здания так, как программисты пишут программы, то первый залетевший дятел разрушил бы цивилизацию
Аватар вне форума Ответить с цитированием
Старый 08.08.2012, 13:25   #5
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Цитата:
Могу ли я это делать напрямую из своего потока? Или опять таки нужно применять синхронизацию?
из потока напрямую вообще страшно куда-то сунуться... вероятность обломиться - 500%.

Цитата:
Могу ли я это делать напрямую из своего потока? Или опять таки нужно применять синхронизацию?
Я объект-контеинер создаю в теле потока, и до его старта, передаю туда содержимое.

к слову у вас есть Memo, нужно загнать текст в поток.
В Private потока пишем fStrings:TStringList
пишем свойство
property Lines:TStringList read fStrings write fStrings;
в констукторе и дестррукторе описываем fStrings.

До Thread.Resume {Start};
Передаем в Lines потока, Lines от Memo. Thread.Lines.AddStrings(Memo.Lines)
Человек_Борща вне форума Ответить с цитированием
Старый 08.08.2012, 19:23   #6
Базиля
Участник клуба
 
Аватар для Базиля
 
Регистрация: 03.12.2009
Сообщений: 1,013
По умолчанию

Аватар
Благодарю!
Человек_Борща
Спасибо!
Цитата:
До Thread.Resume {Start};
Передаем в Lines потока, Lines от Memo. Thread.Lines.AddStrings(Memo.Lines)
Я может быть не до конца понял вашу мысль, извиняюсь, у меня бесконечный поток реализован, в нем находится бесконечный цикл который каждую секунду осуществляет занос текста в мемо и в этом же потоке я хочу обрабатывать строки обновленного мемо. Как-то так.
Базиля вне форума Ответить с цитированием
Старый 08.08.2012, 19:55   #7
Человек_Борща
Старожил
 
Аватар для Человек_Борща
 
Регистрация: 30.12.2009
Сообщений: 11,426
По умолчанию

Создаете синхронизируемое событие с параметрами, где ваш поток и обьект обмениваются данными.
Код:
 type
  TSyncEvent=procedure (Sender:TObject; var aInThread:TStrings; const aOutThread:TStrings) of object;

type
  TThread1=class(TThread)
  private
  fEvent:TSyncEvent;
  fDataIn:TStringList;
  fDataOut:TStringList;
  public
  property OnSync:TSyncEvent read fEvent write fEvent;
  Exchange(var DataIn:TStrings; const DataOut:TStrings);
  procedure DoSync; 

....
{Тут ололо сотни кода и так далее...}

procedure TThread1.Exchange(var DataIn:TStrings; const DataOut:TStrings);
begin
 fDataIn:=DataIn;
 fDataOut:=DataOut;
 Synchronize(DoSync); //Синхронизировать fEvent невозможно, по этому финт 
end;

procedure TThread1.DoSync;
begin
 if Assigned(fEvent) then
 fEvent(Self, fDataIn, fDataOut);
end;
Таким образом в событии OnSync происходит безопасное передвижение данных между потоком и обьектом синхронизации.
Человек_Борща вне форума Ответить с цитированием
Старый 08.08.2012, 21:53   #8
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
который каждую секунду осуществляет занос текста в мемо
ЗАЧЕМ показвыать мельтешащие буковки?
70% процессорного времени задачи уйдет на бесполезную отрисовку!
и 90% обшего времени поток будет простаивать ожидая выполнения бесполезной отрисовки. (ведь отрисовка тебует синхронизации, т.е. остановки потока).

Цитата:
Вообще, лучшая синхронизация - это та, которую не нужно выполнять. Твоему потоку нужны какие-то данные для работы? Собери их в кучу до запуска потока и передай потоку параметрами по значению (с копированием). Тогда в потоке будет копия всех необходимых данных, к которой можно обращаться в любой момент без необходимости синхронизации.
И также с результатами работы потока (собери и выдай).

Делаем внутрипотоковый объект TStringList.
Заносим в него, обрабатываем, и готовые результаты (малую толику) через синхронизацию сбрасываем в основной поток.

А там глядишь и поток не нужен будет.
TstringList при том же фунционале по обработке строк, работает быстрее TMemo, т.к. ему не надо отвлекаться на дополнительные действия по рисованию себя!
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 08.08.2012 в 21:59.
evg_m вне форума Ответить с цитированием
Старый 09.08.2012, 22:56   #9
Rock-n-Rolla
Форумчанин
 
Регистрация: 11.01.2012
Сообщений: 177
По умолчанию

если в не главном потоке работать с компонентами через Win API, то никакая синхронизация не нужна, система всё синхронизирует за нас. Сообщения отправляются в очередь в главный поток
progromore.i2p - первый русскоязычный портал программистов в скрытосети
Rock-n-Rolla вне форума Ответить с цитированием
Старый 10.08.2012, 03:36   #10
Базиля
Участник клуба
 
Аватар для Базиля
 
Регистрация: 03.12.2009
Сообщений: 1,013
По умолчанию

Человек_Борща
Спасибо за подробное описание, вот сидел - сидел, все пытался разобрать этот кусочек кода и вообще что-то ни к чему не пришел, наверное мой багаж знаний еще мал для того чтобы здесь разобраться.
С пользовательскими событиями дело еще не имел. Стоит наверное разобраться для начала с ними. Чтобы вникать в этот кусочек.
Еще раз спасибо.
evg_m
Цитата:
ЗАЧЕМ показвыать мельтешащие буковки?
70% процессорного времени задачи уйдет на бесполезную отрисовку!
и 90% обшего времени поток будет простаивать ожидая выполнения бесполезной отрисовки. (ведь отрисовка тебует синхронизации, т.е. остановки потока).
От мемо конечно же избавлюсь в дальнейшем и воспользуюсь списком строк У меня сейчас просто проблема немного в другом, почему то если просто создаю (для своего примера) пустой поток - кидаю в него добавление записи в БД, то приложение работает нормально.
Если я в потоке описываю обработку строки и последующее занесение ее в БД, то форма подвисает.
Я уже выяснил что вся загвоздка в куске кода:
Код:
form5.myquery1.SQL.Clear;
form5.myquery1.SQL.Add('бла-бла-бла');
form5.myquery1.active:=true;
Блин, вот честное слово, похоже я немного запутался Даже не знаю с какого места вообще в целом подкрасться.....
Цитата:
Делаем внутрипотоковый объект TStringList.
Заносим в него, обрабатываем, и готовые результаты (малую толику) через синхронизацию сбрасываем в основной поток.
Так тоже пытался сделать, строку из потока сбрасывал через синхронизацию в главный поток для добавления записи - форма тоже подвисает. Делаю добавление записи в потоке - форма подвисает.
Убираю в потоке добавление записей - форма не подвисает.
Создаю пустой проект - кидаю в поток добавление записей, форма не подвисает.

Rock-n-Rolla
Цитата:
если в не главном потоке работать с компонентами через Win API, то никакая синхронизация не нужна, система всё синхронизирует за нас.
Цитата:
Если обращаться в потоке напрямую к какому - либо компоненту, то периодически будет вылазить ошибка "Canvas does not allow drawing".


Спасибо всем кто откликается в теме и помогает мне разобраться в потоках )))) Благодарю!

Последний раз редактировалось Базиля; 10.08.2012 в 03:38.
Базиля вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Потоки в с# qwerty74 C# (си шарп) 5 22.06.2011 13:57
Потоки Killer_Pooh Общие вопросы Delphi 4 01.06.2011 02:28
[C#] Потоки Lemo C# (си шарп) 2 24.05.2011 21:50
Потоки fredwriter Общие вопросы Delphi 20 13.11.2010 04:16
потоки tanek Помощь студентам 6 15.03.2010 21:42