Search code examples
c#.netwpfwcf

How to fix broken Service and return data in WPF with WCF?


I have a WPF application in which i want to return list of data or any data when user call it. Also i need to call WCF service to get data. What if service is down for any reason and i want to fixed broken service or wait for service alive and return the data. Let me show you what i am doing:

    public List<MyData> GetMyData()
    {
           try
           {
               var  data =GetOrCreateChannel().GetMyData(); //GetOrCreateChannel method create WCF service channel
              return data;
           }
           catch(Exception ex)
           {
               _log.error(ex);
                FixedBrokenService()
                return GetMyData(); //Call again this method.
           }
    }

In above method, if service is not running, it will go to catch block and again call the same method until unless service is down. Whenever service get alive, it will return the data. I want to know is this approach is fine or not? What if service is down for 2 to 3 hour it wil recursivly call method and the stack size in memory will increasing. Is there any other approach?


Solution

  • What if service is down for 2 to 3 hour it wil recursivly call method and the stack size in memory will increasing. Is there any other approach?

    I think you're asking because you already sense there might be some other way to improve what you've got so far; my guess is you're looking for some standard.

    If so, I'd recommend Google's Exponential backoff guideline, here applied to Google Maps calls.

    The idea is to introduce a delay between subsequent calls to the web service, increasing it in case of repeated failures.

    A simple change would be:

    public List<MyData> GetMyData()
    {
        List<MyData> data = null;
        int delayMilliseconds = 100;
        bool waitingForResults = true;
    
        while (waitingForResults)
        {
            try
            {
                data = GetOrCreateChannel().GetMyData();
    
                waitingForResults = false; // if this executes, you've got your data and can exit
            }
            catch (Exception ex)
            {
                _log.error(ex);
                FixedBrokenService();
    
                Thread.Sleep(delayMilliseconds); // wait before retrying
                delayMilliseconds = delayMilliseconds * 2; // increase your delay
            }
        }
        return data;
    }
    

    This way you won't have to deal with recursion either; don't forget to add using System.Threading; to the top.


    Since you mentioned WPF, we might want to take Jeroen's suggestion and wait in another thread: this means that your WPF GUI won't be frozen while you try reconnecting, but it will be enabled and perhaps show a spinner, a wait message or something like that (e.g. "Reconnecting in x seconds").

    This requires changing the second to last line, i.e. Thread.Sleep(delayMilliseconds); to Wait(delayMilliseconds); and adding these two methods below GetMyData:

    private async static Task Wait(int delayMilliseconds)
    {
        await WaitAsync(delayMilliseconds);
    }
    
    private static Task WaitAsync(int delayMilliseconds)
    {
        Thread.Sleep(delayMilliseconds);
        return new Task(() => { });
    }