Видимо я не правильно понял суть того IC. Он работает только в параллельном потоке, а я хотел развязать им компоненты, которые выдают данные в поток. Он их не пропускает.
Этот топик читают: Гость
Ответов: 704
Рейтинг: 7
|
|||
карма: 0 |
|
Ответов: 4628
Рейтинг: 749
|
|||
Вообще, при работе с параллельными потоками стоит обратить внимание на две вещи.
Первое - обращение (чтение-запись) к одним и тем же данным из различных потоков. Проблема возникает когда один поток пишет значение переменной, а второй либо пытается читать, либо тоже пишет. И если речь идет об одной переменной - проблемы маловероятны. Но мы работаем с компонентами, которые представляют собой класс. Простая запись значения приводит к вызову целой цепочки методов в дочерних и родительских классах, функций системы, изменения и проверки значений множества полей. И вот когда один поток вызвал метод записи, цепочка которого выполнила часть изменений-проверок, но ещё не все, и в этот момент другой поток выполнил этот или другой метод, который затронул те же данные, с большой вероятностью произойдет какая-либо ошибка. Стоит прояснить: в приложении всегда есть один главный поток. В этом главном потоке в частности исполняется цикл обработки сообщений оконного приложения. Все визуальные компоненты (а также другие компоненты, обрабатывающие сообщения, поступающие в эту очередь) получают команды и изменяют свое поведение во многом через сообщения, вызывая уже свои внутренние методы, как было описано выше. И вот когда в параллельном потоке происходит какое-либо изменение визуального компонента и вызывается метод компонента, может происходить описанная выше ситуация конфликта, только в этом случае конкурирующим потоком стаёт главный поток, который, например, получил сообщение от системы и обработка этого сообщения затронула те же данные, что и параллельный поток. Один из способов решения проблемы, возникающей с очередью сообщений и параллельными потоками, применяется в компоненте потока KOL и используется представленным InlineCode: метод doSynchronize и событие onSync происходят путем посылки оконного сообщения в главный поток. При этом механизм сообщений Windows предполагает, что пока это сообщение не будет обработано, ни одно другое сообщение не перебъет его исполнение, в том числе если сколько угодно других потоков тоже вызовут метод doSynchronize. Таким образом мы получаем некоторый контроль над доступом параллельных потоков к визуальным компонентам. Второе - когда параллельные потоки одновременно работают с невизуальными компонентами. Более общий вариант предыдущего пункта. Поскольку тут нет сообщений, применение предыдущего метода синхронизации хоть и во многих случаях помогает (потоки выполняются последовательно, не перебивая друг друга), но оно имеет свои недостатки: - в неоконных приложениях нет главной очереди сообщений, поэтому до недавнего времени компоненты и схемы с параллельными потоками не имели возможность использовать событие onSyncExec (и предложенный InlineCode). Для этих случаев я предложил компонент MainLoop. - когда потоков много или они слишком часто делают doSynchronize, это фактически переводит многопоточное приложение в однопоточный режим, поскольку потоки стают в очередь и выполняются последовательно. Косвенно это можно заметить и по "тормозам" в интерфейсе приложения. Вот для решения второго пункта используется минимальная защита только того участка схемы, к которому совместно обращаются несколько параллельных потоков. Для этого используются другие механизмы системы - критические секции, мютексы, сигналы. Обратите внимание на вкладку "Система"->"Потоки". Подробно тут описывать конкретное применение компонентов не буду, потому что и сам туда не заглядывал. Расскажу только принцип работы критической секции. Когда нужно оградить некоторый участок схемы от одновременного доступа из нескольких потоков, например, требуется вызвать метод некоторого компонента, перед этим методом мы ставим компонент SafeMode (Mode=Local) и заводим все потоки на этот компонент. Если вдруг два потока вызвали наш метод одновременно, система сама ставит их в очередь и первый по порядку поток выполняет этот метод. Когда он закончит - система пропустит второй поток к этому методу. Таким образом разрушения данных не произойдет. В теории. С некоторой вероятностью. Так как на практике у нас весь код компонентов скрытый, и иногда может быть сложно определить, какие данные какой компонент изменяет и в каком месте надо поставить критическую секцию. В общем, написал много, не могу гарантировать, что всё правильно. Надеюсь, кому-нибудь поможет. Редактировалось 1 раз(а), последний 2017-03-20 12:39:18 |
|||
карма: 26 |
| ||
Голосовали: | Neo, flint2 |
Ответов: 704
Рейтинг: 7
|
|||
Netspirit, то есть "вот она, рыба моей мечты"?
code_32929.txt Или последний абзац я понял неверно? ------------ Дoбавленo в 17.17: Кстати, наверное у меня как раз системный поток конфликтует чаще всего - по поиску кода ошибки выдает System.pas |
|||
карма: 0 |
| ||
файлы: 1 | code_32929.txt [392B] [546] |
Ответов: 4628
Рейтинг: 749
|
|||
Да, вроде так правильно. Только часть схемы после критической секции должна быть минимальной, потому что потоки будут большую часть времени простаивать в очереди.
System.pas - это стандартный модуль Delphi, содержащий базовый набор функций. Если в нем происходит ошибка, то причина может быть в любом компоненте, использующим функции из этого модуля и не только по причине параллельных потоков. |
|||
карма: 26 |
|
Ответов: 2059
Рейтинг: 132
|
|||
Netspirit
Спасибо! Отличные компоненты! Отдельное спасибо за переделанный Thread!!! |
|||
карма: 6 |
|
Ответов: 4628
Рейтинг: 749
|
|||
flint2, пожалуйста. Пользуйся на здоровье.
|
|||
карма: 26 |
|
Ответов: 1058
Рейтинг: 76
|
|||
Netspirit писал(а): В этой схеме применен IC, который демонстрирует возможность вызова события в главном потоке из параллельного потока. -= DriveR =- писал(а): hiThread заменилAssasin писал(а): скопировать файл NSTrhead.pasСделал, выдает HiAsm\Elements\delphi\code\hiInlineCode_92526D0.pas(26) Error: Undeclared identifier: 'CallSynchronized' |
|||
карма: 0 |
|
Ответов: 4628
Рейтинг: 749
|
|||
А версия NSThreads.pas - из первого поста (от 02.01.2014)?
|
|||
карма: 26 |
|
Ответов: 1058
Рейтинг: 76
|
|||
[offtop]
Netspirit писал(а): А версия NSThreads.pasВерно, старая была. Главное скачал новую версию, а каким то боком старую закинул [/offtop] |
|||
карма: 0 |
|
Ответов: 4628
Рейтинг: 749
|
|||
Обновлены компоненты:
- В клиенте и сервере добавлено свойство AsyncEvents, позволяющее обрабатывать события в параллельных потоках. Позволяет избежать тормозов в интерфейсе приложения, но может требовать дополнительных мер при обработке таких событий. Для тестирования запустите примеры клиента и сервера, в клиенте дайте отправку большого (1-2 Мб) текстового файла и во время приема сервером таскайте окно за заголовок. Проведите эксперимент с включенным и отключенным свойством в сервере. - Метод doConnect клиента проходит асинхронно (без ожидания в вызвавшем потоке). Раньше при невозможности подключения вызвавший поток замирал на время таймаута. - В классе потока изменено поведение метода Synchronize при отсутствии возможности синхронизации (в неоконных приложениях без компонента MainLoop). В таком случае метод всеравно вызывается, но в своем потоке. |
|||
карма: 26 |
| ||
Голосовали: | Neo, Konst, sashaoli |
Ответов: 1343
Рейтинг: 31
|
|||
может предвидится сделать тип передаваемых данных?
str, stream... + может добавить перебор или просто встроенный массив IP'ов ну и конечно же не хватает хорошей точки Active особенно у Client |
|||
карма: 2 |
|
Ответов: 824
Рейтинг: 138
|
|||
Netspirit,Огромное, спасибо за измененный NSTrhead.pas!
Теперь в программах стало заметно меньше проблем, или вообще их нет! А то только поставь Trhead в схеме, сразу в программе вечные проблемы. И еще раз - СПАСИБО! |
|||
карма: 1 |
|
Ответов: 4628
Рейтинг: 749
|
|||
Rysik писал(а): может добавить перебор или просто встроенный массив IP'овRysik писал(а): тип передаваемых данныхRysik писал(а): не хватает хорошей точки Active особенно у Clientsashaoli писал(а): И еще раз - СПАСИБО! |
|||
карма: 26 |
|
Ответов: 4628
Рейтинг: 749
|
|||
.....
|
|||
карма: 26 |
|
Ответов: 1343
Рейтинг: 31
|
|||
ммм, а вот как переслать простому TCP клиенту данные ввиде Stream через новый TCP сервер?
механизм TCP клиент модифить нельзя никак! как был так и есть, надо просто как то отправить данные ввиде Stream что бы клиент получил данные как от простого сервера |
|||
карма: 2 |
|