Search code examples
.netasynchronousasync-await.net-4.5long-running-processes

.NET 4.5 Polling Progress Example Please


I want to run a long running process in a windows service asynchronously - and poll the process every 3 seconds and report back using SignalR. The code below will ( theoretically ) do this in an event based way , but I don't want to be firing of the progress with every single change.

Can someone please provide a simple example of how to implement this specifically to start the process and poll / report progress. Please bear in mind I have been out of full time development for a few years!

public async Task<string> StartTask(int delay)
{
    var tokenSource = new CancellationTokenSource();
    var progress = new Progress<Tuple<Int32, Int32>>();

    progress.ProgressChanged += (s, e ) =>
    {
        r2hProcessesProxy.Invoke("DownloadNotify", string.Format("Major={0} - Minor={1}", e.Item1 , e.Item2  ));
    };

    var task = DownloadTask.DoDownload(delay, tokenSource.Token, new Progress<Tuple<Int32,Int32>>(p => new Tuple<Int32, Int32>(0,0)));

    await task;

    return "Task result";
}

Solution

  • You can do this with the use of Reactive Extensions (Rx). Check the Throttle() method: https://msdn.microsoft.com/en-us/library/hh229400(v=vs.103).aspx

    using System;
    using System.Linq;
    using System.Reactive.Linq;
    using System.Threading.Tasks;
    
    public class Test
    {
        public async Task<string> StartTask(int delay)
        {
            var tokenSource = new CancellationTokenSource();
            var progress = new Progress<Tuple<Int32, Int32>>();
    
            var observable = Observable.FromEvent<EventHandler<Tuple<Int32, Int32>>, Tuple<Int32, Int32>>(h => progress.ProgressChanged += h, h => progress.ProgressChanged -= h);
            var throttled = observable.Throttle(TimeSpan.FromSeconds(3));
    
            using (throttled.Subscribe(e =>
            {
                r2hProcessesProxy.Invoke("DownloadNotify", string.Format("Major={0} - Minor={1}", e.Item1, e.Item2));
            }))
            {
                await DownloadTask.DoDownload(delay, tokenSource.Token, new Progress<Tuple<Int32, Int32>>(p => new Tuple<Int32, Int32>(0, 0)));
            }
    
            return "result";
        }
    }
    

    Check http://go.microsoft.com/fwlink/?LinkId=208528 for more info about RX