Доброго времени суток!

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

Буду благодарен любым идеям.

UPD-1. Изначально не известно сколько будет подпроцессов, поэтому такого рода схема не подойдет

Нравится

12 комментариев

Здравствуйте!

что то вроде такого -http://prntscr.com/ocm1ol

Вот наглядный пример, создал 3 БП, в них добавил разные таймеры и посмотрим как идет обработка в главном БП

http://prntscr.com/ocmaqq - Главный

http://prntscr.com/ocmaxg - 1 мин задержки

http://prntscr.com/ocmb6t - 2 мин задержки

http://prntscr.com/ocmbg8 - 3 мин задержки



Запускаем основной и смотрим диаграму:

http://prntscr.com/ocmc05

http://prntscr.com/ocmc9u

http://prntscr.com/ocmck4 - завершился (диаграма выполнения основного без изменения - http://prntscr.com/ocmcso)

http://prntscr.com/ocmda0

Нигрескул Алексей,

Обновил описание вопроса

Если процессы создаёте кодом, то можно их количество записать в определённое поле, а в конце дочернего процесса отнимать от значения единицу. На изменение поля на ноль в основном процессе повесить сигнал.

Зверев Александр,

А где создавать это поле? И как сделать обработчик сигнала?

В каком-то объекте, подходящем по логике, с которым по смыслу связаны эти процессы. Обработчик — сигнал на изменение поля в объекте.

Зверев Александр,

То есть нужно в дочернем процессе сначала считать эту колонку селектом затем сделать update? НО если эти дочерние процессы завершаться секунда в секунду, то подсчет не будет верным. Как быть тогда?

Уменьшать и считывать старое значение можно в том же запросе.

Зверев Александр,

Гарантируется ли при использовании этого запроса правильный подсчет одновременно завершающихся подпроцессов?

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

Зверев Александр,

Зверев Александр пишет:Уменьшать и считывать старое значение можно в том же запросе.

Через такой запрос не генерится сигнал 

Действительно, в таком случае используйте не Update, а ESQ. Синхронизацию в этом случае нужно предусмотреть самостоятельно. Либо же менять при помощи Update, а в следующем шаге менять другое поле по ESQ или посылать сигнал иным образом.

Показать все комментарии

Добрый день! Есть скрипт, который выполняется около 5-7 минут, вызываемый с помощью меню "действия" пользователем, на это время террасофт находится в состоянии бездействия, хотелось бы чтобы в этот момент появлялось окно с надписью "Выполняется расчет показателей...", а по окончанию расчета выдавало "Расчет окончен" и исчезало, чтобы пользователь не пытался что-то нажать, думая что у него подвисла машина..
Подскажите пожалуйста как можно реализовать данную задачу.

Заранее огромное спасибо!

Нравится

12 комментариев

Здравствуйте!
Какая у Вас версия?

3.2.0.10
MS SQL

Да, можно. Аналогично сделано в массовом удалении. Посмотрите функции:
DeleteAllRecordsFromOpenedDataset из scr_BaseGridAreaUtils
wnd_BaseGridAreaOnNotify и amiDeleteAllOnExecute из scr_BaseGridArea

ок, спасибо! посмотрю.

Добрый день! Посмотрел пример, вот что у меня получилось:

for (var a = 0; a < AccountDataset.RecordsCount ; a++){
	var Complete = 100 - (( (AccountDataset.RecordsCount - a)/AccountDataset.RecordsCount ) * 100); //Выполнение в %
	var ProgressCaptionMessage = FormatStr(ProgressCaptionMsg, Complete);
	var Caption = '';
	var Prompt = '';
	var WithCancel = false; // For DeleteAll progress window WithCancel parameter is not used
	var ShowModal = false;
	var ProgressWindowType = pwt_DeleteAll;  
	var ProgressWindow = BeginProcessingProgress(Self, Caption, Prompt,
		WithCancel, ShowModal, ProgressWindowType);
    InternalSetCaptionForProcessingProgress(ProgressWindow, Self, ProgressCaptionMessage);
    ProgressWindow.Close();
 
    //Затем выполняются необходимые операции по данному контрагенту
 
 AccountDataset.GotoNext();
	}
AccountDataset.Close();

Получается если не закрывать окно ProgressWindow.Close(); - то окон будет появляться столько сколько контрагентов, если закрывать то перед глазами отображается не очень приятная картина, постоянно мелькает окно(закрывается, открывается и т.д.)
Подскажите пожалуйста что тут еще можно подправить? Заранее спасибо!

Добрый день. А почему бы не вызывать окно ProgressWindow перед выполнением цикла и соответственно закрыть после всех итераций?
Кроме того, по тексту скрипта есть одно замечание. Свойство датасета RecordsCount при обращении к нему каждый раз порождает запрос типа "SELECT COUNT(*) FROM ...", что значительно замедляет работу. Есть смысл занести это значение один раз после открытия датасета в переменную и в дальнейшем обращаться уже к этой переменной.

За RecordsCount спасибо, но если вызывать ProgressWindow перед выполнением цикла, то не будет видно прогресса выполнения расчета..

Разобрался, вот может кому пригодиться:

var QuantityCounts = AccountDataset.RecordsCount;
        var ProgressCaptionMessage = "Выполняется расчет показателей...";
        var Caption = '';
        var Prompt = '';
        var WithCancel = false; // For DeleteAll progress window WithCancel parameter is not used
        var ShowModal = false;
        var ProgressWindowType = pwt_DeleteAll;  
        var ProgressWindow = BeginProcessingProgress(Self, Caption, Prompt,
                WithCancel, ShowModal, ProgressWindowType);
        BaseGridArea.ProgressWindow = ProgressWindow;
	SetAttribute(ProgressWindow, 'NotifyObject', Self);
	var SelfWindow = ActionMenuItem.ParentWindow; 
 
	InternalSetCaptionForProcessingProgress(ProgressWindow, SelfWindow, ProgressCaptionMessage);
 
for (var a = 0; a < QuantityCounts ; a++){
 
       var Complete = Math.round( a / QuantityCounts *	100);//Выполнение в %
       InternalSetPromptForProcessingProgress(ProgressWindow, SelfWindow ,	Complete + ' %');
       InternalMoveProcessingProgress(ProgressWindow, SelfWindow , Complete);
 
 
 
    //Затем выполняются необходимые операции по данному контрагенту
 
 AccountDataset.GotoNext();
        }
AccountDataset.Close();
 ProgressWindow.Close();

Здравствуйте, коллеги!

Скажите, пожалуйста, а как со скоростью выполнения скрипта?
Мне кажется, что после добавления Progress Bar, субъективно, скрипт начал медленней работать...
Пример кода (только вызываю своё окно):

var QuantityCounts = 1000;
pbSecondProgress.MaxPosition = QuantityCounts;
 
for (pbSecondProgress.Position = 0; pbSecondProgress.Position < QuantityCounts ; pbSecondProgress.Position++){
        System.ProcessMessages();
}
 
 ShowInformationDialog('Всё!!!!!!!!');

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

System.ProcessMessages() может замедлить выполнение скрипта. Если итераций много и каждая итерация занимает мало времени, возможно есть смысл вызывать эту функцию на на каждую n-ную итерацию.

Есть еще одно решение - добавить в окно 2 таймера. Первый таймер запустить на событии OnPrepare() окна, второй - при завершении процесса. Соответственно в событии OnTimer() первого запускается сам процесс, а на OnTimer() второго закрывается окно. Время можно указать для обоих - 1 сек.

Такое решение очень удобно, когда необходимо запускать в командной строке определенное окно, которое запускает определенный процесс:
TSCRM.exe /wnd=wnd_MyProcess

Показать все комментарии