Вверх ↑
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
#31: 2014-01-26 13:58:22 ЛС | профиль | цитата
Видимо я не правильно понял суть того IC. Он работает только в параллельном потоке, а я хотел развязать им компоненты, которые выдают данные в поток. Он их не пропускает.
карма: 0

0
Ответов: 4621
Рейтинг: 746
#32: 2014-01-26 16:43:30 ЛС | профиль | цитата
Вообще, при работе с параллельными потоками стоит обратить внимание на две вещи.

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

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

Один из способов решения проблемы, возникающей с очередью сообщений и параллельными потоками, применяется в компоненте потока KOL и используется представленным InlineCode: метод doSynchronize и событие onSync происходят путем посылки оконного сообщения в главный поток. При этом механизм сообщений Windows предполагает, что пока это сообщение не будет обработано, ни одно другое сообщение не перебъет его исполнение, в том числе если сколько угодно других потоков тоже вызовут метод doSynchronize.
Таким образом мы получаем некоторый контроль над доступом параллельных потоков к визуальным компонентам.

Второе - когда параллельные потоки одновременно работают с невизуальными компонентами. Более общий вариант предыдущего пункта. Поскольку тут нет сообщений, применение предыдущего метода синхронизации хоть и во многих случаях помогает (потоки выполняются последовательно, не перебивая друг друга), но оно имеет свои недостатки:
- в неоконных приложениях нет главной очереди сообщений, поэтому до недавнего времени компоненты и схемы с параллельными потоками не имели возможность использовать событие onSyncExec (и предложенный InlineCode). Для этих случаев я предложил компонент MainLoop.
- когда потоков много или они слишком часто делают doSynchronize, это фактически переводит многопоточное приложение в однопоточный режим, поскольку потоки стают в очередь и выполняются последовательно. Косвенно это можно заметить и по "тормозам" в интерфейсе приложения.
Вот для решения второго пункта используется минимальная защита только того участка схемы, к которому совместно обращаются несколько параллельных потоков. Для этого используются другие механизмы системы - критические секции, мютексы, сигналы.

Обратите внимание на вкладку "Система"->"Потоки". Подробно тут описывать конкретное применение компонентов не буду, потому что и сам туда не заглядывал. Расскажу только принцип работы критической секции.

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

В общем, написал много, не могу гарантировать, что всё правильно. Надеюсь, кому-нибудь поможет.

Редактировалось 1 раз(а), последний 2017-03-20 12:39:18
карма: 26

2
Голосовали:Neo, flint2
Ответов: 704
Рейтинг: 7
#33: 2014-01-26 17:17:34 ЛС | профиль | цитата
Netspirit, то есть "вот она, рыба моей мечты"?
code_32929.txt
Или последний абзац я понял неверно?
------------ Дoбавленo в 17.17:
Кстати, наверное у меня как раз системный поток конфликтует чаще всего - по поиску кода ошибки выдает System.pas
карма: 0

0
файлы: 1code_32929.txt [392B] [502]
Ответов: 4621
Рейтинг: 746
#34: 2014-01-26 18:09:01 ЛС | профиль | цитата
Да, вроде так правильно. Только часть схемы после критической секции должна быть минимальной, потому что потоки будут большую часть времени простаивать в очереди.

System.pas - это стандартный модуль Delphi, содержащий базовый набор функций. Если в нем происходит ошибка, то причина может быть в любом компоненте, использующим функции из этого модуля и не только по причине параллельных потоков.
карма: 26

0
Ответов: 2059
Рейтинг: 131
#35: 2014-01-27 10:08:37 ЛС | профиль | цитата
Netspirit
Спасибо!
Отличные компоненты!
Отдельное спасибо за переделанный Thread!!!
карма: 6

0
Ответов: 4621
Рейтинг: 746
#36: 2014-01-30 12:17:12 ЛС | профиль | цитата
flint2, пожалуйста. Пользуйся на здоровье.
карма: 26

0
Ответов: 1073
Рейтинг: 76
#37: 2014-02-10 23:49:54 ЛС | профиль | цитата
Netspirit писал(а):
В этой схеме применен IC, который демонстрирует возможность вызова события в главном потоке из параллельного потока.

-= DriveR =- писал(а):
hiThread заменил
Assasin писал(а):
скопировать файл NSTrhead.pas

Сделал, выдает
HiAsm\Elements\delphi\code\hiInlineCode_92526D0.pas(26) Error: Undeclared identifier: 'CallSynchronized'

карма: 0

0
Ответов: 4621
Рейтинг: 746
#38: 2014-02-11 12:08:11 ЛС | профиль | цитата
А версия NSThreads.pas - из первого поста (от 02.01.2014)?
карма: 26

0
Ответов: 1073
Рейтинг: 76
#39: 2014-02-11 19:09:23 ЛС | профиль | цитата
[offtop]
Netspirit писал(а):
А версия NSThreads.pas

Верно, старая была.
Главное скачал новую версию, а каким то боком старую закинул
[/offtop]
карма: 0

0
Ответов: 4621
Рейтинг: 746
#40: 2014-02-18 12:38:34 ЛС | профиль | цитата
Обновлены компоненты:

- В клиенте и сервере добавлено свойство AsyncEvents, позволяющее обрабатывать события в параллельных потоках.
Позволяет избежать тормозов в интерфейсе приложения, но может требовать дополнительных мер при обработке таких событий.
Для тестирования запустите примеры клиента и сервера, в клиенте дайте отправку большого (1-2 Мб) текстового файла и во время приема сервером таскайте окно за заголовок. Проведите эксперимент с включенным и отключенным свойством в сервере.

- Метод doConnect клиента проходит асинхронно (без ожидания в вызвавшем потоке). Раньше при невозможности подключения вызвавший поток замирал на время таймаута.

- В классе потока изменено поведение метода Synchronize при отсутствии возможности синхронизации (в неоконных приложениях без компонента MainLoop). В таком случае метод всеравно вызывается, но в своем потоке.
карма: 26

3
Голосовали:Neo, Konst, sashaoli
Ответов: 1342
Рейтинг: 31
#41: 2014-02-21 20:48:16 ЛС | профиль | цитата
может предвидится сделать тип передаваемых данных?

str, stream...

+ может добавить перебор или просто встроенный массив IP'ов

ну и конечно же не хватает хорошей точки Active особенно у Client
карма: 2

0
Ответов: 824
Рейтинг: 138
#42: 2014-02-22 12:10:02 ЛС | профиль | цитата
Netspirit,Огромное, спасибо за измененный NSTrhead.pas!
Теперь в программах стало заметно меньше проблем, или вообще их нет!
А то только поставь Trhead в схеме, сразу в программе вечные проблемы.
И еще раз - СПАСИБО!
карма: 1

0
Ответов: 4621
Рейтинг: 746
#43: 2014-02-22 13:05:24 ЛС | профиль | цитата
Rysik писал(а):
может добавить перебор или просто встроенный массив IP'ов
doEnumClients, в процессе перебора точка CurIPAddress содержит IP

Rysik писал(а):
тип передаваемых данных
Прием в Stream - не вижу никаких сложностей (исп. DataToFile). Передача из стрима - в примерах предложено конвертировать стрим в строку. Если предполагается передавать большие файлы (больше 100 Мб), можно в схеме сделать чтение стрима небольшими частями.

Rysik писал(а):
не хватает хорошей точки Active особенно у Client
А что она должна показывать? Работает ли ещё соединение? Во-первых, можно ловить событие onDisconnect, во-вторых, в некоторых случаях нельзя обнаружить разрыв соединения до тех пор, пока не отправишь по нему данные. Таким образом, нужно будет периодически посылать другой стороне какой-нибудь условный запрос и обрабатывать onDisconnect. Это можно сделать в схеме. [offtop]Правда, в API есть встроенная возможность посылать такие пакеты, но пока не проверял.[/offtop]

sashaoli писал(а):
И еще раз - СПАСИБО!
Пожалуйста
карма: 26

0
Ответов: 4621
Рейтинг: 746
#44: 2014-02-28 17:02:21 ЛС | профиль | цитата
.....
карма: 26

0
Ответов: 1342
Рейтинг: 31
#45: 2014-05-24 20:43:12 ЛС | профиль | цитата
ммм, а вот как переслать простому TCP клиенту данные ввиде Stream через новый TCP сервер?
механизм TCP клиент модифить нельзя никак! как был так и есть, надо просто как то отправить данные ввиде Stream что бы клиент получил данные как от простого сервера
карма: 2

0
Сообщение
...
Прикрепленные файлы
(файлы не залиты)