Поиск:

Ответ в темуСоздание новой темы Создание опроса
> Почему нельзя освободить память из-под потока? FreeOnTerminate = true --> исключение 
:(
    Опции темы
Valeri
Дата 14.3.2007, 09:22 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 2.2.2007

Репутация: нет
Всего: нет



Так ведь Synchronize нужна, чтобы предотвратить одновременный доступ к одному и тому же объекту. В моей программе только поток чтения обращается к объектам

Form1->Nsect=Form1->Data.RecByte1
                        Form1->Fh=(Form1->Data.RecByte2)+((Form1->Data.RecByte3)*255);
                                        
                        Form1->Label20->Caption=IntToStr(Form1->Data.RecByte1);
                        Form1->Label21->Caption=IntToStr(Form1->Data.RecByte2);
                        Form1->Label23->Caption=IntToStr(Form1->Data.RecByte3);
                        Form1->Label24->Caption=IntToStr(Form1->Fh); 



, а чтобы не случилось проблем я и пытаюсь притормаживать поток чтения.
PM MAIL   Вверх
ksili
Дата 14.3.2007, 09:33 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Synchronize нужна всегда, когда обраащешься к визуальным компонентам (Form, Label и т.д.) потому что есть ещё основной поток твоей программы, и когда он там к чему обратится неизвестно (событий же куча). Поэтому надо синхронизировать. Попрбуй сделать как я написал, может висяки исчезнут.
Да и здесь на форуме есть несколько тем, где это более-менее описано. А к данной теме синхронизация очень отдалённо относится


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Valeri
Дата 14.3.2007, 09:42 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Новичок



Профиль
Группа: Участник
Сообщений: 16
Регистрация: 2.2.2007

Репутация: нет
Всего: нет



Сделал синхронизацию всех обращений к компонентам VCL из потока, но никакого эффекта - пока в порт не поступают данные программа также виснет при попытке передавать данные в порт. 
Согласен СИнхронизацию не обсуждаем, речь о работе с потоками.

Фишка еще вот в чем -
когда убираю функции Suspend и Resume, то все работает нормально - и чтение идет и запись, но как-то это не красиво: при записи в порт надо остановить чтение. Пока не придумал как.
PM MAIL   Вверх
Vyacheslav
Дата 14.3.2007, 13:13 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(ksili @  13.3.2007,  13:20 Найти цитируемый пост)
А почему нельзя после Resume() писать WaitFor()? Когда вообще тогда WaitFor() писать нужно? 

Если Вы используете FreeOnTerminate = true, то после Resume() вообще обращаться к как либо к объекту TThread  обращаться  опасно. К тому времени, когда Вы  попытаесь обратиться, вполне возможно, что он уже завершился и в о

Цитата

Warning:    When FreeOnTerminate is true, the Execute method may run and then free the thread before your application can execute the next line of code. Thus, you should not call any methods of the thread object when FreeOnTerminate is true unless you create the thread in a suspended state.

Вольный перевод
Цитата

Предупрежение. Когда FreeOnTerminate  установлен в true,  Execute метод может быть уже сработать  и затем освободить поток до того как Ваше  приложение сможет выполнить следующую строчку кода. Поэтому Вы не должны вызывать любое методы объекта потока, когда FreeOnTerminate  установлен в true, за исключением случая, когда Вы создали поток в подвешанном состоянии.


Что касается использования  WaiteFor, то все очень просто.   WaitFor как раз должен следовать за Resume, но не следующей сточкой smile
Код

td = new TDispThread(true);
td->Resume();

// далаем что-то  основном потоке
// еще  что-то  делаем  основном потоке
// и еще  что-то  делаем  основном потоке

// закончили делать и нам нужны результаты работы потока
// поэтому ждем завершения потока
td-> WaiteFor();
// здесь что-то делаем с результами работы потока

// при необходимости удаляем
delete td;  

То есть в отличие от вашего кода мы имеем участок, когда идет паралельное выполнение в основном и дочернем потоке. А WaiteFor() в данном случае приминяется для синхронизации этих потоков. Мы же не знаем, кто завершит свой код раньше основной поток или дочерний. Но такое поведене справедливо при FreeOnTerminate= false



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
pandrew
Дата 14.3.2007, 18:10 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Бывалый
*


Профиль
Группа: Участник
Сообщений: 213
Регистрация: 27.3.2006

Репутация: 3
Всего: 3



Цитата(Vyacheslav @  13.3.2007,  13:09 Найти цитируемый пост)
Добавлено @ 13:17 
Цитата(pandrew @  13.3.2007,  10:27 )
Для потока с FreeOnTerminate = true; завершение делается так:

Грубая ошибка. Во-первых к моменту вызова Terminate поток может уже завершиться и td уничтожиться. Во-вторых, даже если поток еще работает, то он может успеть завершиться и уничтожиться после Terminate, но  до вызова  WaitFor.


Читаем: 
TThread::Terminate
Signals the thread to terminate by setting the Terminated property

Так что утверждение про разрушение td между вызовами сомнительно.
Я всегда пишу потоки как бесконечную петлю обработки (иначе не понимаю зачем они нужны), поэтому самозавершения потоков у меня не бывает. Бывают правда исключение в потоковой функции, которые приводят к завершению, если не обрабатываются. Но я всегда рулю всеми потоками из главного без проблем по указанному варианту.
В вашей логике те же грабли: любой вызов td может быть некорректен, ибо td уже разрушен
PM MAIL   Вверх
Vyacheslav
Дата 14.3.2007, 20:32 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Экс. модератор
Сообщений: 2124
Регистрация: 25.3.2002
Где: Москва

Репутация: 47
Всего: 59



Цитата(pandrew @  14.3.2007,  18:10 Найти цитируемый пост)
Читаем: 
TThread::Terminate
Signals the thread to terminate by setting the Terminated property

Так что утверждение про разрушение td между вызовами сомнительно.
Я всегда пишу потоки как бесконечную петлю обработки (иначе не понимаю зачем они нужны), поэтому самозавершения потоков у меня не бывает. Бывают правда исключение в потоковой функции, которые приводят к завершению, если не обрабатываются. Но я всегда рулю всеми потоками из главного без проблем по указанному варианту.
В вашей логике те же грабли: любой вызов td может быть некорректен, ибо td уже разрушен 

Причем тут это? Вы вводную читали?
Цитата(ksili @  12.3.2007,  11:08 Найти цитируемый пост)
Создаю его по событию таймера. Событие возникает каждые 3 секунды  (а не 2 как раньше написал, извиняюсь). За это время он успевает завершиться

Поток успевает завершиться сам, а не принудительно через Terminate. И таких задач, где нет бесконечного цикла  навалом. Если Вы не встречали в своей практике, это еще не значит, что их нет. 
Так что Ваш код для данного случаЯ ошибочен. Поток во-первых может завершиться сам до вызова Terminate. 
Ну а если Вы этот же код используете у себя и при этом у вас есть цикл с проверкой Terminated и FreeOnTerminate == true, то код  

Код

td->Terminate();
td->WaitFor();td=0;

опасен все равно. Потому что есть вероятность, что Вы можете схлопотать эксепшен на вызове WaitFor(). Надеяться на то, что между вызовами Terminate и WaitFor объект не успеет разрушится, неразумно. Если уж очень хочется обнулить td то логичнее и безопаснее смотрелось бы
 
Код

td->Terminate();
td=0;


smile
 
 



--------------------
С уважением, Вячеслав Ермолаев
PM MAIL WWW ICQ   Вверх
ksili
Дата 15.3.2007, 05:30 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



У меня основной целью было не обнулить td, а чтобы не росла занимаемая программой память из-за постоянно создаваемых потоков.
В принципе я уже переделал основные потоки, к-рые создаются моей программой, по типу бесконечной петли обработки, но есть ещё поток, который создаётся время от времени.
 
О, прямо сейчас придумал! А если и этот поток делать как бесконечную петлю обработки, но, поскольку он должен выполняться эпизодически, ввести дополнительное условие:
Код

while(!Terminated)
    {
     if(flag)
        {
         .....
        }
    }

А флаг просто менять из того потока, который должен активировать этот


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
dumb
Дата 15.3.2007, 07:36 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


sceloglauxalbifacies
****


Профиль
Группа: Экс. модератор
Сообщений: 2929
Регистрация: 16.6.2006

Репутация: 32
Всего: 158



Цитата(ksili @  15.3.2007,  05:30 Найти цитируемый пост)
О, прямо сейчас придумал!

тебе не надо ничего придумывать. вместо этого лучше прочитай пару-тройку статей про потоки и синхронизацию.

твой поток можно сделать, например, так:
Код

  HANDLE hEvent = CreateEvent(0,0,0,"vasya");
  while(!Terminated)
  {
    WaitForSingleObject(hEvent, INFINITE);
    ...
  }
  CloseHandle(hEvent);


когда нужно, чтобы рабочий поток выполнил "...", в основном потоке делаешь:
Код

  HANDLE hEvent = OpenEvent(0,0,"vasya");
  if (hEvent)
  {
    SetEvent(hEvent);
    CloseHandle(hEvent);
  }

PM MAIL   Вверх
ksili
Дата 15.3.2007, 07:48 (ссылка) | (нет голосов) Загрузка ... Загрузка ... Быстрая цитата Цитата


Эксперт
****


Профиль
Группа: Завсегдатай
Сообщений: 2069
Регистрация: 3.11.2005
Где: Красноярск

Репутация: 1
Всего: 17



Да, суть та же, только писанины больше. Всё равно же, все эти апишные функции (как впрочем и все), по сути - обёртки для обычных mov eax, ecx  smile (в нашем случае - mov flag, 1). А, по-моему, чем проще, тем надёжнее и быстрее


--------------------
Ничто так не развивает аналитическое мышление, как отладка сложной программы без возможности пошагового выполнения (с)
PM MAIL   Вверх
Ответ в темуСоздание новой темы Создание опроса
Правила форума "С++ Builder"
Rrader

Запрещается!

1. Публиковать ссылки на вскрытые компоненты

2. Обсуждать взлом компонентов и делиться вскрытыми компонентами

  • Литературу по С++ Builder обсуждаем здесь
  • Действия модераторов можно обсудить здесь
  • С просьбами о написании курсовой, реферата и т.п. обращаться сюда
  • Настоятельно рекомендуем заглянуть в DRKB (Delphi Russian Knowledge Base) - крупнейший в рунете сборник материалов по Дельфи


Если Вам понравилась атмосфера форума, заходите к нам чаще! С уважением, Rrader.

 
0 Пользователей читают эту тему (0 Гостей и 0 Скрытых Пользователей)
0 Пользователей:
« Предыдущая тема | C++ Builder | Следующая тема »


 




[ Время генерации скрипта: 0.0556 ]   [ Использовано запросов: 22 ]   [ GZIP включён ]


Реклама на сайте     Информационное спонсорство

 
По вопросам размещения рекламы пишите на vladimir(sobaka)vingrad.ru
Отказ от ответственности     Powered by Invision Power Board(R) 1.3 © 2003  IPS, Inc.