Top.Mail.Ru

D365. Синхронные и асинхронные операции

Есть несколько способов выполнения трудоемких операций в веб-клиенте D365. Всем знакомо ощущение, когда выполняется трудоемкая операция, операция блокирует весь пользовательский интерфейс до тех пор, пока он не будет завершен, показывая белый экран или ожидающее сообщение. Чтобы избежать этого, в Dynamics AX 2012 используется progress bar, который отображает прогресс выполнения операции для пользователя или другие возможности асинхронного выполнения, например Thread API или метод xApplication::runAsync(), чтобы запустить операцию в фоновом режиме.

В D365 оптимизирование трудоемких операций особенно важно, потому что они запускаются в веб-интерфейсе, который будет заблокирован или сессия завершится по времени ожидания. По этой причине рекомендуется использовать асинхронный режим выполнения. Новая форма импорта данных использует такой подход.
Давайте посмотрим на различные возможности для запуска трудоемких операций.

Чтобы протестровать их, создадим простую форму, как ниже:

Затем создадим новый класс со статическим методом, который будет содержат программный код, который содержит паузу на 10 секунд.

public class TestOperation
{
	public static container returnAfteraWhile(container _callerparameters)
	{
		str caller = conPeek(_callerparameters, 1);

		sleep(10000);

		return(['Operation completed : ' + caller]);
	}
}

На первом этапе тестирования выполнение программного кода будет происходит в синхронном режиме. При нажатии на первую кнопку вызовем статический метод тестового класса напрямую. Отобразится стандартное сообщение “Please wait” и интерфейс будет заблокирован.

[Control("Button")]
class CallNormal
{
	public void clicked()
	{
		super();

		TestOperation::returnAfteraWhile(['Syncronous operation..']);
		info('Syncronous operation finished.');
	}
}

Для второй кнопки напишем код, который выполнит этот же метод, но будемт использоваться новый класс SysOperatonSandbox механизма SysOperation.

Control("Button")]
class CallSysOperationSandbox
{
	public void clicked()
	{
		super();

		SysOperationSandbox::callStaticMethod(classNum(TestOperation),
		                                      staticMethodStr(TestOperation,returnAfteraWhile),
		                                      ['Sandbox Run Sync'], 
		                                      'Waiting for sandbox operation', 
		                                      'Operation completed');
	}
}

После запуска, на экране появится диалоговое окно, но пользовательский интерфейс по прежнему будет заблокирован.

Чтобы запустить программный код в асинхронном режиме без блокирования пользовательского интерфейса, в AX 2012 для этой цели использовались метод xApplication::runAsync() или механизм Thread. Сейчас они уже устарели и были заменены новым методом runAsync в классах FormRun и Global, который использует .NET Tasks для многопоточного выполнения.
Для тех кто не знаком с асинхронным выполнением, асинхронный метод будет вызван и запущен в фоновом режиме, без взаимодействия с пользовательским интерфейсом. В завершении, метод вызовет другой метод, который является callback методом. Создадим callback метод в тестовой форме, код представлен ниже.

public void FormCallBackTest(AsyncTaskResult _result)
{
	container result, resultinfolog;
	str       resultStr;

	info('Async operation finished.');
	result    = _result.getResult();
	resultStr = conPeek(result, 1);

	info(resultStr);

	resultinfolog = _result.getInfologData();

	if (resultinfolog != conNull())
	{
		setPrefix('Extra information');
		InfoLogExtension::showMessagesFromContainer(resultinfolog);
	}
}

Вызовем метод returnAfteraWhile используя новый метод runAsync класса FormRun.

[Control("Button")]
class CallElementRunAsync
{
	public void clicked()
	{
		super();

		info('process is running..');

		element.runAsync(classNum(TestOperation), 
		                 staticMethodStr(TestOperation, returnAfteraWhile),
		                 ['Element Run Async'],
		                 System.Threading.CancellationToken::None, 
		                 formMethodStr(AsyncTestForm, FormCallBackTest));
	}
}

Данный код выполнит статический метод в фоновом режиме и при завершении вызовет callback метод передав в него объект AsyncTaskResult в качестве параметра. Данный объект является контейнером, который возвращает асинхронный метод. Из контейнера можно получить сообщения и результат выполнения асинхронного метода.

Если нажать на третью кнопку форму, то будет видно, что интерфейс пользователя останется доступным и на экран сразу будет выведено сообщение о завершении после выполнения метода.

Метод runAsync класса FormRun оптимизирован для выполенния на стороне клиента. Есть другой метод runAsync в классе Global, который используется в коде, который запускается внеклиента, например в качестве сервиса. В четвертой кнопке будем использовать именно метод класса Global и будет видна разница между ними.
Для этого необходимо создать новый callback метод, но уже в тестовом классе.

public static void ClassCallBackTest(AsyncTaskResult _result)
{
	container result, resultinfolog;
	str       resultStr;

	info('Async operation finished.');
	result    = _result.getResult();
	resultStr = conPeek(result, 1);

	info(resultStr);

	resultinfolog = _result.getInfologData();

	if (resultinfolog != conNull())
	{
		setPrefix('Extra information');
		InfoLogExtension::showMessagesFromContainer(resultinfolog);
	}

}

Для кнопки напишем следующий код:

[Control("Button")]
class CallGlobalRunAsync
{
	public void clicked()
	{
		super();

		info('process is running..');
		Global::runAsync(classNum(TestOperation), 
		                 staticMethodStr(TestOperation, returnAfteraWhile), 
		                 ['Global Run Async'],
		                 System.Threading.CancellationToken::None, 
		                 classNum(TestOperation), 
		                 staticMethodStr(TestOperation, ClassCallBackTest));
	}
}

Теперь при нажатии кнопки метод returnAfteraWhile будет запущен в фоном режиме. Но сообщения не будут отображены после заверешения выполнения, потому что асинхронный и callback методы выполнялись внеклиента и обработчик формы не знает ничего об запущеном процессе. Чтобы увидеть сообщения требуется обновить форму.

 

source

Comments

So empty here ... leave a comment!

Добавить комментарий

Sidebar