0

I'm working on an Xamarin.Forms application with MVVM. In my viewmodel I want to Get all the patients from an API. This is the code:

public async Task GetAllPatients()
        {
            try
            {
                isFetchingData = true;
                var response = await httpClient.GetStringAsync(baseUrl + "/patient?query=ma");

                var resultPatients =
                    JsonConvert.DeserializeObject<ObservableRangeCollection<PatientViewModel>>
                    (testJson,jsonSerializerSettings);

                AllPatients.ReplaceRange(resultPatients);
                Patients.ReplaceRange(resultPatients);
            }
            catch(Exception e)
            {
                Console.WriteLine("*****ERROR kon API niet ophalen");
                Console.WriteLine(e.Message);
            }
            finally
            {
                CheckIfEmptyList();
                isFetchingData = false;
            }
        }

At first I just got the API hard coded from a json string (testJson) in my code and everything went smoothly. But from the moment I put the htppClient out of commentary something strange happens (even when I don't use the variable as you can see in the code(I get the same result when I do use the variable though)).

The finally block is not executed.

It is to say, when I go and debug the app, the code goes through the finally and checks if the list is empty and puts isFetchingData to false. But I don't see that happening on the screen. If the list is empty a label should occur but now that label doesn't go away when list is not empty. The INotifyPropertyChanged does work good because without the httpClient it runs smoothly.

I'm very new to asynchronous programming so maybe I forgot to implement something that has to make sure the GetStringAsync ends properly? Maybe it keeps fetching the data and that is why I never see the finally block executed (even though it does behind the screen). I've read some articles about asynchronous programming but couldn't find something that could help me out.

I must also say that this method is called from the constructor, which makes it a little bit harder to run async. I tried calling it without async await and I tried calling it this way:

Task.Run(async ()=> { await GetAllPatients(); });

I tried with and without ConfigureAwait(false) but that doesn't make a difference either.

Marijke
  • 153
  • 3
  • 14
  • 1
    Task.Run won't be running on the UI thread. I think you are getting an exception but not catching it. – Crowcoder May 18 '18 at 10:27
  • @Crowcoder I think I'm too new to the concept to understand what you mean. Can you be more precise in what you mean? Perhaps give an example of what I can do to fix the problem? – Marijke May 18 '18 at 11:11
  • Task.Run will execute code on a thread pool thread but you can only make UI updates from the main UI thread. Google people like Cleary, Toub, Skeet. You should refactor so you don't need Task.Run anyway, in addition to the thread problem, it is not appropriate for I/O operations. – Crowcoder May 18 '18 at 11:18

1 Answers1

0

Finding a way to not put the method in the constructor (as suggested by CrowCoder and Albert) seemed the only possibility. In this case I managed to do so, but for other people it may not be always possible.

Because I work with MVVM without a framework and I'm very new to Xamarin and asynchronous programming (I'm a student), it was too difficult for me to find an alternative to the constructor.

I will put this as an answer, but if someone can give a code example where it would work to put the method in the constructor, or a workaround, it is still very welcome.

Marijke
  • 153
  • 3
  • 14