Вижу что тема Вам не сильно интересна, хотя казалось что даже очень.
Чтоб закрыть её, вот как можно сделать прогресс для обычного RunBase :
X++:
class Test_RunBaseBatch extends RunBaseBatch
{
DialogField dfDuration;
// Packed variables
int duration;
str csvFileContent;
Email email2Send;
guid callId;
#define.CurrentVersion(1)
#localmacro.CurrentList
callId,
duration,
csvFileContent,
email2Send
#endmacro
SysOperationProgressWait progressWait;
//SysProgress sysProgress;
public object dialog()
{
DialogRunbase dialog;
dialog = super();
dfDuration = dialog.addFieldValue(identifierStr(Integer),duration,"Duration (Sec.)");
return dialog;
}
public boolean getFromDialog()
{
boolean ret;
ret = super();
duration = dfDuration.value();
email2Send = SysUserInfo::getUserEmail(curUserId());
return ret;
}
public container pack()
{
return [#CurrentVersion,#CurrentList];
}
public void runAsync()
{
callId = newGuid();
progressWait = SysOperationProgressWait::construct();
progressWait.parmCallId(callId);
progressWait.parmCaption(this.caption());
progressWait.parmBatchTaskId(0);
xGlobal::runAsyncWithObjectCallback(
classNum(Test_RunBaseBatch),
staticMethodStr(Test_RunBaseBatch, doRunAsync),
this.pack(),
this, methodStr(Test_RunBaseBatch, runAsyncCallback));
Message::Add(MessageSeverity::Informational ,"Start Operation Async");
progressWait.beginWaiting();
}
private void runAsyncCallback(AsyncTaskResult _result)
{
progressWait.endWaiting();
Message::Add(MessageSeverity::Informational ,"End Operation Async");
container parms = _result.getResult();
this.unpack(parms);
this.runAfterOperation();
}
private static container doRunAsync(container _parms, System.Threading.CancellationToken cancellationToken)
{
Test_RunBaseBatch runbase = new Test_RunBaseBatch();
runbase.unpack(_parms);
runbase.run();
return runbase.pack();
}
public void run()
{
Message::Add(MessageSeverity::Informational ,"run");
if (! this.validate())
throw error("");
SysOperationProgressServer progressBar = new SysOperationProgressServer(1,false,callId);
progressBar.setCaption("SysOperationProgressServer !!!");
progressBar.setTotal(duration);
commaStreamIo iO = commaStreamIo::constructForWrite();
container header = ["Num"];
iO.writeExp(header);
int i;
for (i=1; i<=duration; i++)
{
iO.write(i);
progressBar.incCount();
progressBar.setText(strFmt("%1 / %2",i,duration));
sleep(1000);
}
System.IO.Stream stream = iO.getStream();
stream.Position = 0;
System.IO.StreamReader reader = new System.IO.StreamReader(stream);
csvFileContent = reader.ReadToEnd();
if (this.isInBatch())
{
this.runAfterOperation();
}
Message::Add(MessageSeverity::Informational ,"Done!");
}
public void runAfterOperation()
{
info("runAfterOperation");
Filename filename = "file.csv";
System.Byte[] byteArray = System.Text.Encoding::Unicode.GetBytes(csvFileContent);
System.IO.MemoryStream stream = new System.IO.MemoryStream(byteArray);
stream.Position = 0;
if (this.isInBatch())
{
if (SysEmailDistributor::validateEmail(email2Send))
{
SysMailerMessageBuilder messageBuilder = new SysMailerMessageBuilder();
messageBuilder.setFrom(email2Send,"@SYS115063")
.addTo(email2Send)
.setPriority(1)
.setSubject(this.caption())
.setBody(this.caption())
.addAttachment(stream, fileName);
SysMailerFactory::sendNonInteractive(messageBuilder.getMessage());
info(strFmt("CSV file %1 Sent to user on e-mail %2",filename,email2Send));
}
}
else
{
File::SendFileToUser(stream, fileName);
info(strFmt("CSV file %1 Sent to user",filename));
}
}
public boolean unpack(container packedClass)
{
Version version = RunBase::getVersion(packedClass);
;
switch (version)
{
case #CurrentVersion:
[version,#CurrentList] = packedClass;
break;
default:
return false;
}
return true;
}
public boolean validate(Object _calledFrom = null)
{
if (false)
return checkFailed("");
return true;
}
static ClassDescription description()
{
return "Test RunBase Descr.";
}
static void main(Args args)
{
Test_RunBaseBatch runBase;
runBase = new Test_RunBaseBatch();
runBase.init();
if (runBase.prompt())
{
runBase.runAsync();
}
}
protected boolean canRunInNewSession()
{
return false;
}
}
Очевидно, что для того, чтобы во время выполнения кода на сервере была возможность взаимодействовать с пользователем, необходимо выполнять операцию асинхронно, а для того, чтобы связать серверный процесс с интерфейсом стали использовать таблицу SysProgress, в нее пишется вся необходимая информация о прогрессе (один или несколько прогресс-баров, заголовок, текст, и т.д) и обновляется в время выполнения.
Надеюсь проделанная мной работа не напрасна и пригодится кому то еще кроме меня. Возможно даже удостоится переноса в Блог.