Вверх ↑
Ответов: 4628
Рейтинг: 749
#1: 2019-01-11 15:56:45 ЛС | профиль | цитата
nesco писал(а):
Оформи его с расширением Ex, добавим
Не надо никаких "Ex" - при открытии старых схем просто отвалятся старые связи на компонент. Функционал компонента никак не изменился. PS: убрать строчку "_event_onCreate: THI_Event;" в коде - упустил.

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

Add(InfoTip,11282530,560,721)
{
Info=#151:Ошибка "Self Destruction" - получаем сигнал и пытаемся очистить, когда событие контейнера ещё не отработало. Нужно Sleep (DeferredEvent слабо поможет) |
Width=197
Height=123
}
Add(MainForm,2953706,24,105)
{
Width=306
Height=264
Caption="Dynamic multithread"
Position=1
link(onCreate,15188141:doEvent1,[])
}
Add(Label,5227359,14,175)
{
Left=5
Top=10
Width=66
Height=17
Caption="Количество:"
}
Add(Edit,2248716,238,98)
{
Left=70
Top=5
Text="10"
}
Add(Button,12182706,77,301)
{
Left=125
Top=5
Width=95
Caption="Запустить"
link(onClick,7554984:doStart,[])
}
Add(Memo,2950724,623,112)
{
Left=5
Top=40
Width=280
Height=185
ScrollBars=2
}
Add(MultiElementEx,490853,763,301)
{
Mode=1
link(onFinish,10736544:doEvent1,[])
}
BEGIN_SDK
Add(EditMultiEx,9576897,21,21)
{
WorkCount=#5:##add|8:##select|7:##clear|7:doStart|
EventCount=#8:onThread|8:onFinish|
VarCount=#12:##eventIndex|
Width=566
Height=375
Point(##add)
Point(##select)
Point(##clear)
Point(##eventIndex)
link(doStart,11741187:doEvent1,[])
}
Add(Thread,1264527,105,119)
{
Delay=100
link(onExec,3660277:doNext,[])
}
Add(Hub,11741187,56,42)
{
link(onEvent1,4473815:doRandom,[])
link(onEvent2,1264527:doStart,[(88,55)(88,125)])
}
Add(Random,4473815,112,42)
{
Min=5
Max=30
link(onRandom,3660277:doMax,[(216,48)(216,132)])
}
Add(CounterEx,3660277,252,119)
{
Min=1
Default=1
Point(doMax)
Point(onThroughMax)
link(onNext,14584811:doSafeMode,[(362,125)(362,27)])
link(onThroughMax,16713849:doEvent1,[])
}
Add(Hub,16713849,329,126)
{
link(onEvent1,14740393:doSafeMode,[])
link(onEvent2,1264527:doStopFlag,[(368,139)(368,169)(93,169)(93,132)])
}
Add(SafeMode,14740393,441,126)
{
Name="Conatiner"
link(onSafeMode,9576897:onFinish,[(528,132)(528,34)])
AddHint(-11,36,60,13,Name)
}
Add(SafeMode,14584811,441,21)
{
Name="Conatiner"
link(onSafeMode,9576897:onThread,[])
AddHint(-11,36,60,13,Name)
}
Add(InfoTip,4383503,392,203)
{
Info=#69:Критическая секция на выходы контейнера - для защиты внутреннего кода|
Width=162
Height=67
}
END_SDK
Add(LineBreakEx,12595872,420,266)
{
Caption="count"
Type=2
}
Add(LineBreakEx,13591516,238,140)
{
Caption="count"
Type=3
link(_Data,2248716:Text,[])
}
Add(For,14344520,413,301)
{
Start=1
link(onEvent,490853:##add,[])
link(End,12595872:getVar,[])
}
Add(Hub,885081,245,301)
{
OutCount=4
link(onEvent1,14344520:doFor,[])
link(onEvent2,15466093:doData,[(343,314)(343,440)])
link(onEvent3,14303809:doFor,[(316,321)(316,587)])
link(onEvent4,13512247:doWait,[(295,328)(295,699)])
}
Add(LineBreakEx,10675697,427,546)
{
Caption="count"
Type=2
}
Add(For,14303809,420,581)
{
Start=1
link(onEvent,3351173:doOperation,[])
link(End,10675697:getVar,[])
}
Add(Random,3466891,112,112)
{
Min=5
Max=30
}
Add(Synchronize,3342322,574,112)
{
link(onSync,2950724:doAdd,[])
}
Add(DoData,15466093,441,434)
{
link(onEventData,6300903:doWork,[])
link(Data,5504863:getVar,[])
}
Add(StrCat,16352581,903,308)
{
Str1="Finished: "
link(onStrCat,9193338:doWork,[])
link(Str2,490853:##eventIndex,[(916,296)(891,296)(891,354)(769,354)])
}
Add(Hub,11666581,595,343)
{
link(onEvent1,490853:##select,[(643,349)(643,314)])
link(onEvent2,490853:doStart,[(655,356)(655,328)])
}
Add(Math,3351173,476,581)
{
OpType=1
Op2=1
link(onResult,11666581:doEvent1,[(581,587)(581,349)])
}
Add(MultiElementEx,10113316,903,490)
{
}
BEGIN_SDK
Add(EditMultiEx,9531177,21,21)
{
WorkCount=#11:CreateEvent|52:doInit=Инициализировать количество ожидаемых потоков|9:doRelease|7:doReset|
VarCount=#6:Handle|
Width=489
Height=207
link(CreateEvent,13285598:doCreate,[(206,27)(206,76)])
link(doInit,1398212:doEvent1,[(76,34)(76,83)])
link(Handle,13285598:ObjHandle,[(27,188)(223,188)])
link(doRelease,6878072:doNext,[(59,41)(59,76)])
}
Add(Events,13285598,217,70)
{
Name=""
}
Add(CounterEx,6878072,140,70)
{
Min=1
Max=999999
Default=1
Point(onThroughMax)
Point(doMax)
link(onThroughMax,13285598:doSet,[])
AddHint(-39,71,21,13,Min)
AddHint(7,71,21,13,Default)
}
Add(Hub,1398212,98,77)
{
link(onEvent1,6878072:doMax,[])
link(onEvent2,13285598:doReset,[(158,120)])
}
Add(InfoTip,7586110,21,252)
{
Info=#110:Если бы крит. секции не было бы в потоках, то она должна была бы быть внутри семафора (на уменьшение счетчика)|
Width=491
Height=39
}
END_SDK
Add(LineBreak,10971451,812,490)
{
Caption="ev"
link(Out,10113316:CreateEvent,[])
Primary=[5375141,-700,-336]
}
Add(Hub,15188141,70,119)
{
link(onEvent1,3466891:doRandomize,[])
link(onEvent2,5375141:In,[(102,132)(102,160)])
}
Add(LineBreakEx,16279675,763,511)
{
@Color=5614250
Caption="init"
}
Add(LineBreakEx,703590,812,511)
{
@Color=5614250
Caption="init"
Type=1
link(OnEvent,10113316:doInit,[(855,517)(855,503)])
}
Add(LineBreakEx,15151214,763,532)
{
@Color=16755285
Caption="rel"
}
Add(LineBreakEx,13981404,812,532)
{
@Color=16755200
Caption="rel"
Type=1
link(OnEvent,10113316:doRelease,[(865,538)(865,510)])
}
Add(InfoTip,8456654,728,462)
{
Info=#21:Реализация "семафора"|
Width=246
Height=123
}
Add(LineBreakEx,5151982,903,553)
{
@Color=11184895
Caption="H"
Type=2
}
Add(LineBreakEx,5362847,903,532)
{
@Color=11184895
Caption="H"
Type=3
link(_Data,10113316:Handle,[])
}
Add(Thread,7554984,175,301)
{
Delay=0
FastStop=0
link(onExec,885081:doEvent1,[])
}
Add(LineBreakEx,5077185,840,315)
{
@Color=16755285
Caption="rel"
}
Add(LineBreakEx,6300903,490,434)
{
@Color=5614250
Caption="init"
}
Add(LineBreakEx,5504863,441,406)
{
Caption="count"
Type=2
}
Add(InfoTip,4446107,378,238)
{
Info=#24:Создание внутренних схем|
Width=169
Height=109
}
Add(InfoTip,3376183,364,511)
{
Info=#59:Запуск потоков только когда все были созданы (во избежание)|
Width=204
Height=123
}
Add(InfoTip,4977800,378,357)
{
Info=#85:Инициализация "семафора" - просигналить, когда указаное количество потоков отработает|
Width=183
Height=123
}
Add(InfoTip,14650480,364,651)
{
Info=#32:Ожидание завершения всех потоков|
Width=400
Height=214
}
Add(Hub,10736544,812,308)
{
link(onEvent1,16352581:doStrCat,[])
link(onEvent2,5077185:doWork,[])
}
Add(LineBreakEx,9193338,959,308)
{
Caption="log"
}
Add(LineBreakEx,5903133,525,112)
{
Caption="log"
Type=1
link(OnEvent,3342322:doSynchronize,[])
}
Add(LineBreakEx,3980463,567,693)
{
Caption="log"
}
Add(DoData,9308539,469,693)
{
Data=String(Все потоки завершились)
link(onEventData,10662999:doEvent1,[])
}
Add(LineBreakEx,6051718,420,665)
{
@Color=11184895
Caption="H"
Type=2
}
Add(WaitObject,13512247,420,693)
{
link(onWait,9308539:doData,[])
link(ObjHandle,6051718:getVar,[])
}
Add(LineBreakEx,1030803,658,798)
{
Caption="destroy"
}
Add(LineBreakEx,8310483,686,315)
{
Caption="destroy"
Type=1
link(OnEvent,490853:##clear,[])
}
Add(Hub,10662999,525,693)
{
link(onEvent1,3980463:doWork,[])
link(onEvent2,8551758:doDeferredEvent,[(546,706)(546,804)])
}
Add(DeferredEvent,8551758,609,798)
{
link(onDeferredEvent,1030803:doWork,[])
}

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

Хотя я раньше назвал этот принцип "семафором", он отличается от принципа одноименного стандартного объекта Windows. Поэтому, чтобы не было путаницы, если когда-то будет создан такой компонент, то назвать его стоит иначе.
Это как бы "условный Events" или "подсчитываемый Events".
карма: 26

0
Редактировалось 5 раз(а), последний 2019-01-12 12:32:19