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

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

Вернуться   Форум программистов > Клуб программистов > Свободное общение
Регистрация

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

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

Ответ
 
Опции темы Поиск в этой теме
Старый 30.09.2013, 07:52   #1
zumm
БохЪ
Форумчанин
 
Аватар для zumm
 
Регистрация: 30.09.2009
Сообщений: 724
По умолчанию Синхронизация одного потока

Что за бред я написал в названии темы? Вот и я думаю...

Но, для начала, вопрос к модератору: ничего страшного, что я пишу эту тему в разделе свободного общения? Ведь я не делаю привязку к языку. Или стояло выбрать другой раздел?

А теперь суть вопроса:
Имеется функция, внутри которой создается поток который что-то там делает, не суть что. Сама функция ждет, пока поток закончит свои дела. Ждет она при помощи WaitForSingleObject: делается вызов WaitForSingleObject с лимитом ожидания 50 мс, потом идет проворот оконной петли с помощью PeekMessage и PM_REMOVE, что бы окошки могли себя отрисовать, потом опять вызов WaitForSingleObject и тд. До тех пор, пока WaitForSingleObject возвращает WAIT_TIMEOUT.

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

Для синхронизации работы с этим объектом при вызове функции из нескольких потоков приложения я использую критическую секцию:

Код:
EnterCriticalSection(LockSection);
...
инициализация_данных_объекта();
создание_потока();
...
LeaveCriticalSection(LockSection);
Все это замечательно работает. Но, если привязать вызов функции к двум разным кнопкам, а потом быстро нажать на них (то есть, что бы второй вызов произошел до того, как отработает первый), то данные нашего объекта внутри потока-обработчика окажутся пустыми.

Для меня это какая-то магия. Как может один и тот же поток работать асинхронно относительно самого себя Подозреваю что это связано с проворотом оконной петли... Но, что характерно, если использовать вот такую "синхронизацию" при помощи флага:

Код:
переменная "флаг" логического типа = false;

начало_функции;
  повторять
    сон(1);
    проворот_оконной_петли();
  пока флаг = true;

  флаг = true;

  ...
  работа_функции();
  ...

  флаг = false;
конец_функции;
То приложение виснет в бесконечном цикле.

Кто нибудь может объяснить, что вообще происходит
В планах порабощение вселенной...
zumm вне форума Ответить с цитированием
Старый 30.09.2013, 09:43   #2
the_deer_one
Участник клуба
 
Аватар для the_deer_one
 
Регистрация: 04.04.2010
Сообщений: 1,554
По умолчанию

а ты уверен что обработчики кнопок в одном потоке работают?
the_deer_one вне форума Ответить с цитированием
Старый 30.09.2013, 09:43   #3
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
Но, что характерно, если использовать вот такую "синхронизацию" при помощи флага:
А кто меняет флаг кроме этой самой функции? никто.
Default значение =false. Вот и висим ждем пока этот никто поменяет нам флаг для выхода.

Цитата:
инициализация_данных_объекта();
создание_потока();
т.к. инициализация идет ДО создания потока, то стало быть поток использует ВНЕШНИЕ (общие для ВСЕХ вновь создаваемых потоков данные).

и все потоки будут пользоваться ПОСЛЕДНЕЙ копией исходных данных.
(заданных по нажатию ВТОРОЙ кнопки !)

Цитата:
используется некий внешний объект, данные в котором инициализируются при вызове функции, а очищаются внутри создаваемого функцией потока.
1 поток после счета очищает (ОБЩИЕ!) данные, которые второй поток уже инициализировал, но еще не просчитал.

инициализация первым
инициализация вторым
очистка первым
Второму достались ОЧИЩЕННЫЕ!!

потоки не должны заниматься ВНЕШНИМИ данными. Задача очистки должна выполняться ВНЕ потока, после того как мы дождались его выполнения.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 30.09.2013 в 09:53.
evg_m вне форума Ответить с цитированием
Старый 30.09.2013, 10:00   #4
zumm
БохЪ
Форумчанин
 
Аватар для zumm
 
Регистрация: 30.09.2009
Сообщений: 724
По умолчанию

the_deer_one, конечно. Да и если бы они работали в разных потоках то все было бы гладко.

evg_m,

Цитата:
А кто меняет флаг кроме этой самой функции? никто.
Default значение =false. Вот и висим ждем пока этот никто поменяет нам флаг для выхода.
Эм, что?

Цитата:
т.к. инициализация идет ДО создания потока, то стало быть поток использует ВНЕШНИЕ (общие для ВСЕХ вновь создаваемых потоков данные).

и все потоки будут пользоваться ПОСЛЕДНЕЙ копией исходных данных.
(заданных по нажатию ВТОРОЙ кнопки !)
Может вы не заметили, я использую критическую секцию для синхронизации. Почему такое происходит без синхронизации я понимаю.

Проблема появляется если я запускаю функцию дважды в ОДНОМ потоке. Как такое реально, я не понимаю.
В планах порабощение вселенной...

Последний раз редактировалось zumm; 30.09.2013 в 10:08.
zumm вне форума Ответить с цитированием
Старый 30.09.2013, 10:24   #5
the_deer_one
Участник клуба
 
Аватар для the_deer_one
 
Регистрация: 04.04.2010
Сообщений: 1,554
По умолчанию

Может у тебя критическая секция отрабатывает, а поток продолжает работать?
the_deer_one вне форума Ответить с цитированием
Старый 30.09.2013, 10:32   #6
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

после того как вошли в цикл проверки флага НИКТО извне не может поменять, а мы сами не может выйти!
итак это ПЕРВЫЙ вызов (и flag=false )
Код:
repeat
... // ЗДЕСЬ нет изменения флага, и ВНЕ тоже!
until  ЖДЕМ пока НИКТО не сможет поменять флаг.

Может вы не заметили, я использую критическую секцию для синхронизации
Цитата:
запускаю функцию дважды в ОДНОМ потоке.
какую функцию, в каком потоке?
Цитата:
Имеется функция, внутри которой создается поток который что-то там делает, не суть что.
Цитата:
Но, если привязать вызов функции к двум разным кнопкам, а потом быстро нажать на них
получите ДВА одинаковых потока, работающих асинхронно! если основная работа потока ВСЕ критической секции. (а иначе зачем он?)
Цитата:
Как может один и тот же поток работать асинхронно относительно самого себя
асинхронно к другой копии.
КАК на это влияет ВАША критическая секция? НЕ знаю, т.к. ее место при работе (не создании!) потока неизвестно.

P.S. чтобы не писать "проворот оконной петли" логичнее использовать (передавать потоку!) CallBack функцию для получения извещения от том что все готово.
программа — запись алгоритма на языке понятном транслятору

Последний раз редактировалось evg_m; 30.09.2013 в 11:03.
evg_m вне форума Ответить с цитированием
Старый 30.09.2013, 10:50   #7
zumm
БохЪ
Форумчанин
 
Аватар для zumm
 
Регистрация: 30.09.2009
Сообщений: 724
По умолчанию

Цитата:
ЗДЕСЬ нет изменения флага, и ВНЕ тоже!
Похоже я вас запутал своим псевдо-языком. Это как блоксхема, нарисовано всегда пост условие, а на деле это может быть и предусловие. Цикл выглядит вот так:

Код:
while(flag)
{
  //проворот петли
}
Цитата:
какую функцию, в каком потоке?
Может вот так будет понятнее:

Код:
SomeObject: SomeType;

function ThreadProcedure(AParametr: Integer): Integer;
{
  //получение ссылки на объект SomeObject из AParametr
  //работа с SomeObject
  //очистка данных в SomeObject
}

function SomeFunction: SomeType;
{
  EnterCriticalSection(LockSection);

  //инициализация данных в SomeObject

  Integer Dummy = 0;
  Integer Thread = BeginThread(nil, 0, @ThreadProcedure, @SomeObject, 0, Dummy);

  if(Thread <> 0)
  {
    while(WaitForSingleObject(Thread, 50) == WAIT_TIMEOUT)
    {
      while(PeekMessage(Message, 0, 0, 0, PM_REMOVE))
      {
        TranslateMessage(Message);
        DispatchMessage(Message);
      }
    }

    CloseHandle(Thread);
  }

  LeaveCriticalSection(LockSection);  
}
В планах порабощение вселенной...
zumm вне форума Ответить с цитированием
Старый 30.09.2013, 11:31   #8
evg_m
Старожил
 
Регистрация: 20.04.2008
Сообщений: 5,526
По умолчанию

Цитата:
while(flag)
{
//проворот петли
}
а что есть кнопочка "снять/поставить флаг"? ее ведь нет, стало быть никто извне (через button.Click) НЕ МОЖЕТ поменять и цикл остается АБСОЛЮТНО бесконечным т.к. ни внутри ни вне нет изменения флага. НЕ ЗАБЫВАЕМ это у нас первый запуск данной процедуры (и данного цикла!)
программа — запись алгоритма на языке понятном транслятору
evg_m вне форума Ответить с цитированием
Старый 30.09.2013, 11:37   #9
zumm
БохЪ
Форумчанин
 
Аватар для zumm
 
Регистрация: 30.09.2009
Сообщений: 724
По умолчанию

Ох. Я думал, проблемой станет не это.

Код:
flag = false; //дефолт

function SomeFunction: SomeType;
{
  while(flag)
  {
    //проворот петли
  }

  flag = true;
  ...
  flag = false;
}
Вызов, в цикл нет входа, ставим флаг, работаем. Пока мы работаем, идет второй вызов, так как влаг стоит, входим в цикл, ждем пока отработает первый вызов. Первый вызов отрабатывает и снимает флаг. Второй вызов выходит из цикла. Дальше сами продолжите?
В планах порабощение вселенной...
zumm вне форума Ответить с цитированием
Старый 30.09.2013, 11:51   #10
the_deer_one
Участник клуба
 
Аватар для the_deer_one
 
Регистрация: 04.04.2010
Сообщений: 1,554
По умолчанию

zumm
Цитата:
проворот оконной петли
откуда ты это выражение взял то?
the_deer_one вне форума Ответить с цитированием
Ответ


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



Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Синхронизация kuba1981 PHP 9 06.05.2013 11:39
Как получить доступ к методу потока(TThread) из основного потока? Pcrepair Общие вопросы Delphi 3 30.03.2013 14:52
проблема при копировании одного столбца из одного файла в другой файл tanunya Помощь студентам 0 24.02.2012 21:30
Должно быть 3 потока. А диспетчер задач показывает, что потока создано 2 BEL9ILLI Общие вопросы Delphi 3 06.12.2011 20:26
Как узнать номер потока из самого потока? GaMeSTeR Помощь студентам 0 03.12.2010 09:50