Search code examples
c#asp.netmultithreadingasync-awaitperiodictimer

Run async method regularly with specified interval


I need to publish some data to the service from the C# web application. The data itself is collected when user uses the application (a kind of usage statistics). I don't want to send data to the service during each user's request, I would rather collect the data in the app and send then all the data in a single request in a separate thread, that does not serve the users requests (I mean user does not have to wait for the request to be processed by the service). For this purpose I need a kind of JS's setInterval analog - the launch of the function each X seconds to flush all collected data to the service.

I found out that Timer class provides somewhat similar (Elapsed event). However, this allows to run the method only once, but that's not a big issue. The main difficulty with it is that it requires the signature

void MethodName(object e, ElapsedEventArgs args)

while I would like to launch the async method, that will call the web-service (input parameters are not important):

async Task MethodName(object e, ElapsedEventArgs args)

Could anyone advise how to solve the described task? Any tips appreciated.


Solution

  • The async equivalent is a while loop with Task.Delay (which internally uses a System.Threading.Timer):

    public async Task PeriodicFooAsync(TimeSpan interval, CancellationToken cancellationToken)
    {
        while (true)
        {
            await FooAsync();
            await Task.Delay(interval, cancellationToken)
        }
    }
    

    It's important to pass a CancellationToken so you can stop that operation when you want (e.g. when you shut down your application).

    Now, while this is relevant for .Net in general, in ASP.Net it's dangerous to do any kind of fire and forget. There are several solution for this (like HangFire), some are documented in Fire and Forget on ASP.NET by Stephen Cleary others in How to run Background Tasks in ASP.NET by Scott Hanselman