Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Начинающим";
Текущий архив: 2011.10.09;
Скачать: [xml.tar.bz2];

Вниз

Синхронизация с основным тредом программы не из TThread   Найти похожие ветки 

 
Дмитрий Белькевич   (2011-06-09 15:48) [0]

Добрый день. С синхронизацией из TThread, в целом, все понятно. Как сделать синхронизацию с основным тредом из треда, от которого есть только Idшник: GetCurrentThreadId?


 
Дмитрий Белькевич   (2011-06-09 15:56) [1]

Нашел классовую процедуру:


TThread.Synchronize(nil, SyncOnTrayLog);


так нормально будет работать?


 
Eraser ©   (2011-06-09 17:16) [2]

вообще, как не единожды показа практика, такого рода синхронизаций, в т.ч. и из TThread лучше избегать, т.к. в итоге все равно придется переделывать потом по той или иной причине. чаще всего хватает OnTerminate или сообщений.


 
misha_gr   (2011-06-10 11:53) [3]

> вообще, как не единожды показа практика, такого рода синхронизаций, в т.ч. и из TThread лучше избегать

А можно поподробней?


 
han_malign   (2011-06-10 16:55) [4]


> от которого есть только Idшник: GetCurrentThreadId?

- ты вообще о чем? Что ты синхронизировать собрался - "Idшник"???
Какие данные принадлежащие основному потоку - изменяются в контексте твоего потока-призрака?


 
Eraser ©   (2011-06-10 17:31) [5]

> [3] misha_gr   (10.06.11 11:53)

Synchronize - прямой путь к дэдлокам и не очевидной логике работы программы.


 
Юрий Зотов ©   (2011-06-10 18:05) [6]

Вообще, лучше, конечно, таких ситуаций изьегать (может быть, стоит пересмотреть логику программы?).

Но если уж очень надо, то можно попробовать так:

1. Найти поток по его ID.
2. Сделать ему suspend.
3. Синхронизироваться с главным потоком.
4. Сделать ему resume.

Но не факт, что это хороший способ. Лучше подумать, как бы этого избежать.


 
Dimka Maslov ©   (2011-06-10 18:44) [7]

Для стандартных средств синхронизации абсолютно неважно какой поток с каким синхронизируется.


 
oxffff ©   (2011-06-10 18:45) [8]

Вопрос не раскрыт. А так QueueUserAPC + Alertable state


 
Dimka Maslov ©   (2011-06-10 18:48) [9]

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


 
Loginov Dmitry ©   (2011-06-10 21:28) [10]


> Вопрос не раскрыт.


+1

Автору стоило бы более подробно раскрыть суть проблемы. На вопрос "как выполнить синхронизацию между потоками" я бы ответил "используй критические секции". Но поскольку не ясна цель синхронизации, невозможно что-либо посоветовать.


 
Loginov Dmitry ©   (2011-06-10 21:35) [11]


> Вообще, лучше, конечно, таких ситуаций изьегать (может быть,
>  стоит пересмотреть логику программы?).
>
> Но если уж очень надо, то можно попробовать так:
>
> 1. Найти поток по его ID.
> 2. Сделать ему suspend.
> 3. Синхронизироваться с главным потоком.
> 4. Сделать ему resume.


Юрий, suspend является deprecated начиная с D2010. Насколько я знаю, в некоторых из популярных языков программирования ситуация аналогичная (насколько помню и Java и .NET (возможно за исключением последних версий) в их числе). И deprecated оно стало не просто так, тому есть веские причины.


 
jack128_   (2011-06-10 21:39) [12]


> Synchronize - прямой путь к дэдлокам и не очевидной логике
> работы программы.

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


 
Юрий Зотов ©   (2011-06-10 23:40) [13]

> И deprecated оно стало не просто так, тому есть веские причины.

Какие?

Я придерживаюсь той точки зрения, что если человек умеет пользоваться инструментом, то этот инструмент ему вполне можно доверять. Ну а если не умеет, то он любым инструментом себе палец оттяпает.


 
Loginov Dmitry ©   (2011-06-11 00:34) [14]


> Какие?


Менеджер памяти в многопоточном приложении синхронизирует операции распределения памяти. Для D7 - с помощью обычной критической секции, в более новых версиях используются другие способы синхронизации (более выгодные в плане производительности). В любом случае есть синхронизация, которая выглядит приблизительно так:
CriticalSection.Enter;
try
 Код распределения памяти
finally
 CriticalSection.Leave;
end;


Представим себе следующий сценарий:
1. Поток "А" запросил выделение памяти. Сработал CriticalSection.Enter. Начал выполняться блок "Код распределения памяти".
2. Поток "В" в этот момент вызвал Suspend потоку "А".
3. Поток "В" запросил выделение памяти. Сработал CriticalSection.Enter. Однако к этому моменту поток "А" уже захватил критическую секцию CriticalSection.

В результате мы получим зависание приложения. Поток "В" никогда не дождется момента освобождения критической секции потоком "А", поскольку поток "А" остановлен (suspended) потоком "В".

Именно по этим причинам Suspended считается deprecated. Отладка многопоточного приложения в Delphi зачастую виснет, судя по всему, по аналогичным причинам.

На королевстве имеется замечательная статья, в которой все сказанное описано более подробно, с примерами (или с ссылками на примеры).


 
Юрий Зотов ©   (2011-06-11 00:47) [15]

Следовательно, suspend надо сделать таким, чтобы он срабатывал только после выхода из критической секции. Но не запрещать совсем.


 
Германн ©   (2011-06-11 01:50) [16]


> Следовательно, suspend надо сделать таким

Объявить deprecated проще.
Ведь сколько уже deprecated было в Дельфи.


 
Eraser ©   (2011-06-11 03:42) [17]

> [12] jack128_   (10.06.11 21:39)

из опыта выделил. десятки ситуаций всяких. можно ли написать грамотный код, который будет работать как часы с помощью Synchronize? - Безусловно можно.


 
Дмитрий Белькевич   (2011-06-12 01:10) [18]


> Автору стоило бы более подробно раскрыть суть проблемы.


Уточняю. Вопрос возник по вот этой причине:

http://delphimaster.net/view/10-1306751915/

>Пытаюсь вызывать из COM сервера процедуру клиента (Events). Когда вызываю из основного потока (с помощью метода Synchronize) - то все происходит нормально - вызов приходит на сторону клиента. Когда же вызов идёт из неоснового потока - событие клиент не получает.

>DiamondShark ©   (01.06.11 11:57) [1]
>В неосновном потоке, конечно же, цикла выборки сообщений нет.

То есть - мне нужен аналог Synchronize для потоков, к которым я не могу обратиться как к TThread"у.

Похоже, что TThread.Synchronize(nil, SomeMethod) делает то, что нужно.


 
sniknik ©   (2011-06-12 01:38) [19]

>> В неосновном потоке, конечно же, цикла выборки сообщений нет.

> То есть - мне нужен аналог Synchronize для потоков, к которым я не могу обратиться как к TThread"у.

?????????????????????

синхронизация потоков с циклом выборки и рядом не лежала...


 
Дмитрий Белькевич   (2011-06-12 10:45) [20]

Да мне, в общем-то не синхронизация как таковая нужна была, но нужно было выполнить часть кода дополнительного потока в основном.

Вообще - как связаны сообщения с событиями (Events) COM сервера я так и не нашел, возможно есть какие-то более изящные механизмы доступа к событиям сервера, чем Synchronize.

В любом случае - спасибо всем ответившим.


 
sniknik ©   (2011-06-12 10:55) [21]

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


 
Loginov Dmitry ©   (2011-06-12 17:56) [22]


> Следовательно, suspend надо сделать таким, чтобы он срабатывал
> только после выхода из критической секции. Но не запрещать
> совсем.


Тогда придется реализацию suspend делать в менеджере памяти. Вряд ли пойдут на это. Да и смысла нет.


 
Loginov Dmitry ©   (2011-06-12 17:57) [23]


> Объявить deprecated проще.


Гораздо проще. Настолько просто, что и Resume досталось. Имхо, незаслуженно.


 
Loginov Dmitry ©   (2011-06-12 18:11) [24]


> Уточняю. Вопрос возник по вот этой причине:
>
> http://delphimaster.net/view/10-1306751915/
>
> >Пытаюсь вызывать из COM сервера процедуру клиента (Events).
>  Когда вызываю из основного потока (с помощью метода Synchronize)
> - то все происходит нормально - вызов приходит на сторону
> клиента. Когда же вызов идёт из неоснового потока - событие
> клиент не получает.
>


Засовывать DCOM в службу, имхо, не самое удачное решение. DCOM, как показывает многолетняя практика, не самая удачная технология. Почему бы Вам не реализовать службу, к примеру, через Indy компоненты (TIdTCPServer / TIdTCPClient) (вполне себе проверенное решение с минимальным количеством подводных камней).


 
Дмитрий Белькевич   (2011-06-12 19:43) [25]


> Засовывать DCOM в службу, имхо, не самое удачное решение.
>  DCOM, как показывает многолетняя практика, не самая удачная
> технология. Почему бы Вам не реализовать службу, к примеру,
>  через Indy компоненты (TIdTCPServer / TIdTCPClient) (вполне
> себе проверенное решение с минимальным количеством подводных
> камней).


Сложности реализации меня не беспокоят - рано или поздно разберусь. Главное - что бы пользователям систему настраивать, по возможности, не пришлось.


 
Loginov Dmitry ©   (2011-06-12 19:55) [26]


> Главное - что бы пользователям систему настраивать, по возможности,
>  не пришлось.


Настройку DCOM никак нельзя назвать легкой. Намного проще написать инструкцию в пару строк о добавлении приложения в список исключений файрволла, чем целую диссертацию о настройках DCOM"а. В простейшем случае настраивать ничего не нужно. Но когда дело дойдет до настройки, тут можно лоб сломать и мозг вывихнуть. Вот один из примеров руководства по настройке DCOM: http://clck.ru/Ece6
Как Вам?


 
Дмитрий Белькевич   (2011-06-13 12:40) [27]


> Как Вам?


Посмотрел. Ад, конечно. Но - у меня более простой случай - локальное соединение, есть надежда, что в большинстве случаем будет работать сразу.


 
Дмитрий Белькевич   (2011-06-13 12:42) [28]

Еще мысль, ведь наверняка можно настройку автоматизировать. Сделать какой-то софт, который всё, что описано в документе http://clck.ru/Ece6 будет делать сам. Имея права, само собой.


 
sniknik ©   (2011-06-13 14:23) [29]

> будет делать сам.
чуть "докрутишь" и готов искусственный интеллект... и нафига тебе "базовая" программа? бросай ее, займись сразу тем, что выгоднее. ("базовую" он тебе потом сам напишет...)

p.s. ты из простой вещи сделал сложную... думаешь осилишь сложное не превратив его в невозможное?


 
Дмитрий Белькевич   (2011-06-13 15:39) [30]


> чуть "докрутишь" и готов искусственный интеллект...


Какой там интеллект, если по пунктам всё в мануале настройки расписано?


> p.s. ты из простой вещи сделал сложную... думаешь осилишь
> сложное не превратив его в невозможное?


Не понял о чем речь. В любом случае - байты везде одинаковые, и компьютер в принципе познаваем.


 
sniknik ©   (2011-06-13 17:03) [31]

> Какой там интеллект
замена админа программой...

> если по пунктам всё в мануале настройки расписано?
а почему у них не программно? если все так просто. и как будет делаться настройка прав, вернее зачем, если права уже есть
> Имея права, само собой.
и как, если их нет.

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

вот вернись к тому с чего начал,  
> Уточняю. Вопрос возник по вот этой причине:
> http://delphimaster.net/view/10-1306751915/
и скажи зачем ты приплел к этому синхронизацию. если там тебе сказали не работает из-за отсутствия цикла выборки.
???


 
Дмитрий Белькевич   (2011-06-13 23:51) [32]


> а почему у них не программно?


Кто же знает - кому-то удобнее мануалы выпускать, чем программы. Мы стараемся сделать так, что бы пользователи минимально настраивали программы, насколько это возможно. Другие (точно знаю: так делают наши прямые российские конкуренты, не буду говорить, кто именно) умышленно делают программы так, что бы без их сервиса настроить (почти) невозможно было. У каждого свой подход.


> и как, если их нет.


RunAs.


> и скажи зачем ты приплел к этому синхронизацию. если там
> тебе сказали не работает из-за отсутствия цикла выборки.
>


Работает, если сделать Synchronize.


 
sniknik ©   (2011-06-14 00:35) [33]

> RunAs.
смешно... буду теперь так админов у себя звать.

> Работает, если сделать Synchronize.
в основном потоке цикл есть. и что? зачем тебе тогда поток?, если из-за цикла (мелочи в общем то) все "одеяло" туда перетягиваешь... работай тогда всегда в основном да и не парь мозг.

никакие сообщения, критические секции и т.д. аналоги, тебе тогда не пойдут, мог бы и не спрашивать "как лучше", только "переключение на работу в основном"...
т.е. идеал у тебя будет "шпыняемый" всеми пример Архангельского... (ну там где вся работа е в синзхроне), ни и, что, что тормозит типа, зато потоки используем...


 
Германн ©   (2011-06-14 02:13) [34]


> т.е. идеал у тебя будет "шпыняемый" всеми пример Архангельского.
> .. (ну там где вся работа е в синзхроне), ни и, что, что
> тормозит типа, зато потоки используем...

Таки да.


 
Дмитрий Белькевич   (2011-06-14 09:00) [35]


> смешно... буду теперь так админов у себя звать.


Если прав нету - то и мануал никак не поможет. Если права есть - и программа справится.


> в основном потоке цикл есть. и что? зачем тебе тогда поток?
> , если из-за цикла (мелочи в общем то) все "одеяло" туда
> перетягиваешь... работай тогда всегда в основном да и не
> парь мозг.


Обращение через основной поток к событиям COM занимает у меня от силы доли процента времени работы дополнительных потоков.


> т.е. идеал у тебя будет "шпыняемый" всеми пример Архангельского.
> .. (ну там где вся работа е в синзхроне), ни и, что, что
> тормозит типа, зато потоки используем...


Я же спрашиваю про варианты. Никто ничего другого пока не предложил. Найду что-то лучше - сделаю по-другому. Пока что оставлю как есть.

p.s. Подумалось... События через механизмы COM всё равно же будут последовательно проходить? То есть - куча потоков одновременно "ломятся" послать событие, но, как ни крути, единомоментно COM передаёт только одно событие. Если так, то что ни делай - быстрее не будет. Так как узкое место - не синхронизация с основным потоком.


 
Дмитрий Белькевич   (2011-06-14 09:03) [36]


> т.е. идеал у тебя будет "шпыняемый" всеми пример Архангельского.
> ..


Всё таки удивительно, как люди дистанционно пытаются ставить кому-то диагнозы и говорить за других. Роды по интернету, чесслово.


 
Дмитрий Белькевич   (2011-06-14 09:03) [37]

Пишу же:

"Все события клиента нужно обязательно синхронизировать? Или можно как-то без этого обойтись?"


 
Дмитрий Белькевич   (2011-06-14 09:16) [38]

В этой же ветке, на найдя лучшего решения, спрашиваю совсем о другом:

"Как сделать синхронизацию с основным тредом из треда, от которого есть только Idшник: GetCurrentThreadId?"

Конкретный же вопрос. Ну нету у меня инстансов класса TThread в некоторых местах программы, что бы из этих инстансов синхронизироваться. Хорошо, что класс TThread умеет переключаться на основной поток, даже без собственного инстанса, без Self"а.

>вообще, как не единожды показа практика, такого рода синхронизаций, в т.ч. и из TThread лучше избегать, т.к. в итоге все равно придется переделывать потом по той или иной причине. чаще всего хватает OnTerminate или сообщений.

Хорошо, отказываемся от Synchronize, делаем сообщение. Что это меняет? Учитывая, что мне нужно синхронно послать сообщение COM клиенту и дождаться от него ответа в виде результат обработки этого сообщения?


 
sniknik ©   (2011-06-14 09:43) [39]

> единомоментно COM передаёт только одно событие.
если один экземпляр, "апартмент" тип вроде то да, но "мульти" это отдельный инстанс в каждом потоке/подключении.

> Так как узкое место - не синхронизация с основным потоком.
естественно не она, она вообще не нужна. нужен цикл выборки.

> Всё таки удивительно, как люди дистанционно пытаются ставить кому-то диагнозы и говорить за других. Роды по интернету, чесслово.
вел бы себя по адекватнее, решал бы именно проблему/по подсказаному (либо сказал почему это не подходит), а не придуманное на ее основании. глядишь родов бы и не было...

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

> Учитывая, что мне нужно синхронно послать сообщение COM клиенту и дождаться от него ответа в виде результат обработки этого сообщения?
раз синхронно, и дождаться + в потоке, нафига вообще события? прямой вызов функции и синхронно и ждет, и результат сразу...
хотя, да понимаю, с учетом моих домыслов (инет родов)  у тебя же основной поток виснет... да?

> Конкретный же вопрос.
без кода? это тебе только так кажется, что конкретный.


 
Дмитрий Белькевич   (2011-06-14 19:29) [40]


> если один экземпляр, "апартмент" тип вроде то да, но "мульти"
> это отдельный инстанс в каждом потоке/подключении.


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

Или связка COM клиент-сервер создаётся на каждый поток приложения?


> прямой вызов функции и синхронно и ждет, и результат сразу.
> ..


Как на стороне сервера вызвать функцию клиента? Кроме событий я ничего не нашел.

Сейчас работает так:

COM сервер имеет COM интерфейс, через который его функции вызывает COM клиент.
COM сервер же через Events обращается к функциям клиента.



Страницы: 1 2 вся ветка

Форум: "Начинающим";
Текущий архив: 2011.10.09;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.58 MB
Время: 0.004 c
2-1308499032
Geo
2011-06-19 19:57
2011.10.09
Fast Report. Количество совпадений из таблицы


15-1308505658
Leon-Z
2011-06-19 21:47
2011.10.09
Иконка *.bmp на кнопке меню.


15-1308074644
Galera
2011-06-14 22:04
2011.10.09
Вирус HTML Crypted.Gen


8-1216110425
deivan
2008-07-15 12:27
2011.10.09
перевод набора фото jpeg в dvd


15-1308265119
Petr V. Abramov
2011-06-17 02:58
2011.10.09
Oracle BI





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