Search code examples
blazorblazor-webassembly

Periodic background task in Blazor wasm


In Blazor wasm, I would like to periodically execute a job (code), even if the user is navigating through the pages (every x min for example).

Is that possible? What would be a practical way?


Solution

  • Create a Service to manage the timer

    public class JobExecutedEventArgs : EventArgs {}
    
    
    public class PeriodicExecutor : IDisposable
    {
        public event EventHandler<JobExecutedEventArgs> JobExecuted;
        void OnJobExecuted()
        {
            JobExecuted?.Invoke(this, new JobExecutedEventArgs());
        }
    
        Timer _Timer;
        bool _Running;
    
        public void StartExecuting()
        {
            if (!_Running)
            {
                // Initiate a Timer
                _Timer= new Timer();
                _Timer.Interval = 300_000;  // every 5 mins
                _Timer.Elapsed += HandleTimer;
                _Timer.AutoReset = true;
                _Timer.Enabled = true;
    
                _Running = true;
            }
        }
        void HandleTimer(object source, ElapsedEventArgs e)
        {
            // Execute required job
    
            // Notify any subscribers to the event
            OnJobExecuted();
        }
        public void Dispose()
        {
            if (_Running)
            {
                // Clear up the timer
            }
        }
    }
    

    Register it in Program.cs

    builder.Services.AddSingleton<PeriodicExecutor>();
    

    Request it and start it in home page initialization

    @page "/home"
    @inject PeriodicExecutor PeriodicExecutor
    
    @code {
        protected override void OnInitialized()
        {
            PeriodicExecutor.StartExecuting();
        }
    }
    

    In any component if you want to do something when job executes

    @inject PeriodicExecutor PeriodicExecutor
    @implements IDisposable
    
    <label>@JobNotification</label>
    
    @code {
    
       protected override void OnIntiialized()
       {
           PeriodicExecutor.JobExecuted += HandleJobExecuted;
       }
       public void Dispose()
       {
           PeriodicExecutor.JobExecuted -= HandleJobExecuted;
       }
    
       string JobNotification;
       void HandleJobExecuted(object sender, JobExecutedEventArgs e)
       {
            JobNotification = $"Job Executed: {DateTime.Now}";
            StateHasChanged();
       }
    }