Forum Xamarin Xamarin.Forms

Am I doing backgrounding correctly?

PhilipOGormanPhilipOGorman USMember ✭✭✭
edited May 2016 in Xamarin.Forms

Most of my apps I need background threads running - where a method is called at a set interval. This is used mostly for communication with peripheral devices.

When updates are need to passed up to the ui thread I raise events on the ui thread from these background tasks/threads.

In the old days on windows i used to create a new thread and loop at an interval. Now I use a Task, is this a correct way of doing things?
Below is the code I use to have a method called in the background continuously.

The class that uses BackgroundWorkerPoll just assigns a method to PollMethod :

            public class BackgroundWorkerPoll : IBackgroundPoll
                {
                    private readonly Object _threadLock = new Object();  
                    private bool _keepGoing = false;
                   private int _sleepMs;
                   private Stopwatch _stopWatch; 

                public BackgroundWorkerPoll(int sleepMs)
                {
                    _sleepMs = sleepMs;
                    _stopWatch = new Stopwatch();
                }

                #region IBackgroundPoll Members

                public Func<bool> PollMethod { get; set; }

                public async void StartPolling()
                {
                    if (_keepGoing)
                    {
                        return; // already running
                    }
                    lock (_threadLock)
                    {
                        _keepGoing = true;
                    }

                    await Task.Run(Poll);
                }

                private async Task Poll()
                {
                    while (_keepGoing)
                    {
                        _stopWatch.Restart();
                        PollMethod();
                        _stopWatch.Stop();
                        var diff = _sleepMs - _stopWatch.ElapsedMilliseconds;
                        if (diff > 0)
                        {
                            await Task.Delay((int)diff);
                        }
                    }
                }

                public void StopPolling()
                {
                    lock (_threadLock) 
                    {
                        _keepGoing = false;
                    }
                }

                #endregion
            }
        }

Best Answers

  • AdamPAdamP AUUniversity ✭✭✭✭✭
    Accepted Answer

    @PhilipOGorman - There doesn't seem to be anything wrong with your implementation, it runs on a separate thread and should tick along nicely.

    Only pointer is to add a try catch around that PollMethod(). If that fails your polling stops.

    Also I would change await Task.Run(Poll); to just Task.Run(Poll); and remove the async on StartPolling.

    Task.Run should also probably have a ContinueWith after it, so that you can handle any errors that may occur and possibly restart the poll if needed.

  • AdamPAdamP AUUniversity ✭✭✭✭✭
    Accepted Answer

    @PhilipOGorman - another way you can catch errors is to do a .ContinueWith((t) => { t.Exception });

    And handle the exception in there.

Answers

  • AdamPAdamP AUUniversity ✭✭✭✭✭
    Accepted Answer

    @PhilipOGorman - There doesn't seem to be anything wrong with your implementation, it runs on a separate thread and should tick along nicely.

    Only pointer is to add a try catch around that PollMethod(). If that fails your polling stops.

    Also I would change await Task.Run(Poll); to just Task.Run(Poll); and remove the async on StartPolling.

    Task.Run should also probably have a ContinueWith after it, so that you can handle any errors that may occur and possibly restart the poll if needed.

  • PhilipOGormanPhilipOGorman USMember ✭✭✭

    @AdamP Thanks for the review! It is hard to find examples of how to do this, I didn't know if I was correct or not.
    Actually it was just this week I added the await to the Task.Run, the reason being that without the await if the Poll method throws an exception it just fails silently in the the background. With the await the exception bubbles up to the UI thread and crashes the app (which I want). It took me a while to figure out what was going wrong.

    stackoverflow.com/questions/17704102/try-catch-outside-of-await-task-run

  • AdamPAdamP AUUniversity ✭✭✭✭✭
    Accepted Answer

    @PhilipOGorman - another way you can catch errors is to do a .ContinueWith((t) => { t.Exception });

    And handle the exception in there.

Sign In or Register to comment.