Перейти к содержанию

Создание фоновой задачи в расширениях толстого клиента

Для того, чтобы создать фоновую задачу в толстом клиенте, которая будет выполнять периодический опрос сервера, следует написать и зарегистрировать расширение, связанное с жизненным циклом приложения ApplicationExtension в проекте Tessa.Extensions.Client.

Ниже приведен пример расширения, которое периодически отправляет запрос на сервер для получения уведомлений по обсуждениям.

class ForumNotificationsApplicationExtension : ApplicationExtension { #region Private Fields

private Timer timer;

private readonly INotificationButtonUIManager manager;

private readonly ILicenseManager licenseManager;

private readonly IFmNotificationProvider notificationProvider;

private readonly ISessionFailedChecker sessionFailedChecker;

private static readonly int forumRefreshInterval = 100;

private int isProcessingRequest;

#endregion

#region Constructors

public ForumNotificationsApplicationExtension( INotificationButtonUIManager manager, ILicenseManager licenseManager, IFmNotificationProvider notificationProvider, ISessionFailedChecker sessionFailedChecker) { this.manager = NotNullOrThrow(manager); this.licenseManager = NotNullOrThrow(licenseManager); this.notificationProvider = NotNullOrThrow(notificationProvider); this.sessionFailedChecker = NotNullOrThrow(sessionFailedChecker); }

#endregion

#region Private Methods

private async void CheckNotificationsAsync(CancellationToken cancellationToken = default) { // Проверяем, что сессия валидна, чтобы, в случае ошибки, не отправлять запросы на сервер if (await this.sessionFailedChecker.IsCurrentSessionFailedAsync(cancellationToken)) { return; }

// Защита от одновременного выполнения запросов в случае, если операция не завершилась до следующего тика таймера if (Interlocked.CompareExchange(ref this.isProcessingRequest, 1, 0) == 0) { try { // Открытие данного контекста позволяет не обновлять время последней активности по сессии await using var _ = SessionRequestTypeContext.Create(SessionRequestType.Background);

this.manager.SetNotificationProvider(this.notificationProvider);

if (await this.manager.IsExistNotificationsAsync(cancellationToken)) { await this.manager.ShowNotificationButtonAsync(false, true, cancellationToken); }

this.manager.SetNotificationProvider(this.notificationProvider); } catch (OperationCanceledException) { throw; } catch (Exception ex) { await this.manager.ShowErrorAsync(ex); } finally { Interlocked.Exchange(ref this.isProcessingRequest, 0); } } }

#endregion

#region BaseOverride

public override async Task Initialize(IApplicationExtensionContext context) { if (!LicensingHelper.CheckForumLicense(await this.licenseManager.GetLicenseAsync(context.CancellationToken), out _)) { return; }

if (this.timer != null) { await this.timer.DisposeAsync(); }

this.timer = new Timer( p => this.CheckNotificationsAsync(), null, 0, forumRefreshInterval); }

public override async Task Shutdown(IApplicationExtensionContext context) { if (this.timer != null) { await this.timer.DisposeAsync(); }

this.timer = null; }

#endregion }

Необходимо зарегистрировать данное расширение:

[Registrator] public sealed class Registrator : RegistratorBase { public override void RegisterUnity() { this.UnityContainer .RegisterType<FmNotificationsApplicationExtension>(new PerResolveLifetimeManager()); } public override void RegisterExtensions(IExtensionContainer extensionContainer) { extensionContainer .RegisterExtension<IApplicationExtension, FmNotificationsApplicationExtension>(x => x .WithOrder(ExtensionStage.AfterPlatform, 1) .WithUnity(this.UnityContainer) .WhenApplications(ApplicationIdentifiers.TessaClient)); } }

Back to top