AXForum  
Вернуться   AXForum > Microsoft Dynamics AX > DAX: Программирование
All
Забыли пароль?
Зарегистрироваться Правила Справка Пользователи Сообщения за день Поиск

 
 
Опции темы Поиск в этой теме Опции просмотра
Старый 25.12.2013, 06:05   #1  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Progress Bar для Batch задачи
По следам бременских музыкантов хотелось бы задать вопрос коллегам, имевшим опыт запуска сразу нескольких экземпляров класса в качестве batch задачи.

После изменения создания progress bar таким образом, чтобы он показывал продвижение во время исполнения, мы видим, как он действительно "ползёт" к 100%, но только для первого запущенного задания!

По достижении 100% он возвращается на меньшее значение, скажем, 23% и "ползёт" снова.

Второй же экземпляр всегда стоит на нуле.

Что происходит при запуске пяти классов, я даже не буду рассказывать в эту рождественскую ночь.

В классе SysOperationProgressServer, который и используется в случае запуска в виде Batch, ничего подозрительного не происходит: ни при создании, ни при setCount -- все параметры передаются нормально.

Какие-нибудь соображения?
__________________
Felix nihil admirari
Старый 27.12.2013, 02:06   #2  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от wojzeh Посмотреть сообщение
По следам бременских музыкантов хотелось бы задать вопрос коллегам, имевшим опыт запуска сразу нескольких экземпляров класса в качестве batch задачи.

Какие-нибудь соображения?
соображения будут у меня же самого в виде отдельного постинга на блоге, а тут вкратце напишу по-русски.

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

во-первых, как было найдено коллегами ранее, параметр, регулирующий вообще запуск прогрессбар на стороне сервера, "заглушен" в вызове RunBase.

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

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

ниже пример вашего класса, который исполняется на сервере как batch, и необходимые коррективы в системных классах.

X++:
void  processSomething()
{

    // maximum number of lines to be processed
    totalLines = ...;
    // to enjoy our boring user during a few next hours...
    this.progressInit("@SYS59011", totalLines, #AviUpdate, 1, null, false, newGuid()); 
 // create the progressbar on the server side if it is not a client session with a new unique GUID

    while (...)
    {
        ...
    }

    progress.kill(true);
}
RunBase
progressInit

X++:
/*
This method is called to initialize the Progress object in runbase.
*/
public void progressInit(
    str                 caption,
    int64               total,
    Filename            animation,
    int                 numOfBars       = 1,
    FormBuildControl    embedded        = null,
    // Begin: Alexey Voytsekhovskiy, bug fix
    boolean             _ifOnSrvBypass = true,
    guid                _callerId       = str2guid('')
    // End: Alexey Voytsekhovskiy, bug fix
    )
{
    if (! progress)
        progress = RunbaseProgress::construct(numOfBars,embedded
        // Begin: Alexey Voytsekhovskiy, bug fix
        // to set progressbar on the server side
                                                                ,_ifOnSrvBypass, _callerId); 
        // End: Alexey Voytsekhovskiy, bug fix

    progress.setCaption(caption);
    progress.setTotal(total);
    progress.setAnimation(animation);
}
RunbaseProgress
construct


X++:
public static RunbaseProgress construct(
    int                 _numOfBars  = 1,
    FormBuildControl    _embedded   = null,
    boolean             _ifOnSrvBypass = true,
    // Begin: Alexey Voytsekhovskiy, bug fix
    guid                _callerId = str2guid('')
    // End: Alexey Voytsekhovskiy, bug fix
    )
{
    return new RunbaseProgress(_numOfBars,_embedded, _callerId, -1, DateTimeUtil::minValue(), _ifOnSrvBypass);
}
kill
X++:
// Begin: Alexey Voytsekhovskiy, reset bug fix
#obsolete void kill(boolean _toKill = false)
{
    this.reset(_toKill);
}
// End: Alexey Voytsekhovskiy, reset bug fix
reset
/
X++:
/ Begin: Alexey Voytsekhovskiy, reset bug fix
void reset(boolean _toKill = false)
// End: Alexey Voytsekhovskiy, reset bug fix
{
    if (oprProgress)
        oprProgress.reset();
    else if (oprProgressServer )
        // Begin: Alexey Voytsekhovskiy,  reset bug fix
        oprProgressServer.reset(_toKill);
        // End: Alexey Voytsekhovskiy, reset bug fix
}
SysOperationProgressServer
reset
X++:
// Begin: Alexey Voytsekhovskiy, reset bug fix
public void reset(boolean _toKill = false)
// End: Alexey Voytsekhovskiy, reset bug fix
{
    UserConnection conn;
    SysProgress progress;
    int i;

    if ( bypass )
        return;

    conn = new UserConnection();
    progress.setConnection(conn);

    conn.ttsbegin();
    try
    {
        // delete existing recoreds for this session.
        delete_from progress
        where progress.SessionIdx == sessionIdx &&
            progress.SessionLoginDateTime == sessionLoginDateTime;

        // create records for this session based on number of bars
        for (i=1; i<=numOfBars; i++)
        {
            // Begin: Alexey Voytsekhovskiy, reset bug fix
            // if the task finished, we have to really kill the progress bar
            if(!_toKill)
            {
            // End: Alexey Voytsekhovskiy, reset bug fix
                select forupdate * from progress where progress.CallId == callId && progress.ProgressIndex == i;

                progress.CallId = callId;

                progress.SessionIdx = sessionIdx;
                progress.SessionLoginDateTime = sessionLoginDateTime;

                progress.ProgressIndex = i;
                // any other default values?
                progress.write();
            }
            // add the recid into the map
            progressRecIds[i] = progress.RecId;
            currentCount[i] = -1;
            currentIncrement[i] = 0;
            total[i] = 0;
            text[i] = '';
        }

        caption = '';
        animation = '';

        ticksAtLastUpdate = 0;

        conn.ttscommit();
    }
    catch
    {
        conn.ttsabort();
    }
}
__________________
Felix nihil admirari
За это сообщение автора поблагодарили: kashperuk (5), Logger (3), Jorj (1), alex55 (1), iCloud (3).
Старый 03.01.2014, 12:16   #3  
kashperuk is offline
kashperuk
Участник
Аватар для kashperuk
MCBMSS
Соотечественники
Сотрудники Microsoft Dynamics
Лучший по профессии 2017
Лучший по профессии 2015
Лучший по профессии 2014
Лучший по профессии 2011
Лучший по профессии 2009
 
4,361 / 2084 (78) +++++++++
Регистрация: 30.05.2004
Адрес: Atlanta, GA, USA
Привет.
Багу создам.
Только вот - не затруднит ли тебя выложить проектик, где видно было бы ошибку сразу, чтобы скриншотов наделать и к багу присобачить?

Спасибо
Старый 03.01.2014, 19:29   #4  
wojzeh is offline
wojzeh
Участник
Аватар для wojzeh
Соотечественники
 
674 / 512 (19) +++++++
Регистрация: 27.04.2006
Адрес: Montreal
Цитата:
Сообщение от kashperuk Посмотреть сообщение
Привет.
Багу создам.
Только вот - не затруднит ли тебя выложить проектик, где видно было бы ошибку сразу, чтобы скриншотов наделать и к багу присобачить?

Спасибо
Иван, собственно тут и не нужен проектик: у всех тасков внутри бача прогресс не меняется -- всегда на нуле, а по окончании -- сразу 100%.

Вот скриншот



А вот детальное описание на английском http://alexvoy.blogspot.ca/2013/12/h...-progress.html
__________________
Felix nihil admirari
 

Похожие темы
Тема Автор Раздел Ответов Посл. сообщение
axinthefield: Optimizing AX Batch Performance - Batch Group Configuration Blog bot DAX Blogs 0 01.04.2011 13:11
axaptapedia: Batch processing Blog bot DAX Blogs 0 29.01.2009 17:05
axaptapedia: Progress Bar Blog bot DAX Blogs 0 21.07.2008 03:39
axaptapedia: Progress Bar Blog bot DAX Blogs 0 27.06.2008 11:05

Ваши права в разделе
Вы не можете создавать новые темы
Вы не можете отвечать в темах
Вы не можете прикреплять вложения
Вы не можете редактировать свои сообщения

BB коды Вкл.
Смайлы Вкл.
[IMG] код Вкл.
HTML код Выкл.
Быстрый переход

Рейтинг@Mail.ru
Часовой пояс GMT +3, время: 04:43.