1

I am building a screen for my app in xamarin.forms the caul is based on a tabbedpage which is built dynamically based on a list of objects which I get as a result of consuming a service. After I call the method to consume the API that brings the list, I need to go through it based on certain data of it to fill an observable collection of viewmodels, which will be the tabs. The problem I have is that I do not know how to call the async method that consumes the API in a synchronized way so that the consumption of the API does not conflict with the operation of going through the list. Then a fraction of the code of my ViewModel:

public MonitoringViewModel()
    {
        LoadThings();
        Tabs = new ObservableCollection<MonitoringTabsViewModel>();
        foreach (PcThing t in Things)
        {
            Tabs.Add(new MonitoringTabsViewModel(t.description));
        }
    }


    private async void LoadThings()
    {
        Things = new List<PcThing>(await App.WebApiManager.GetCustomerThinksAsync());
    }

What I get is that in xamarin live player the app after a few seconds go from the green signal to the red one without showing anything, and in the log of it I get this: Target of GetEnumerator is null (NullReferenceException)

lavilaso
  • 27
  • 7
  • Please review this SO [topic](https://stackoverflow.com/questions/5095183/how-would-i-run-an-async-taskt-method-synchronously). We use it in Production and all works very well. – Alexander I. Nov 18 '18 at 21:05
  • Best way to handle asynchronous code is to make the synchronous code async. Usually there is some kind of event that starts the process that you can mark as async void. As for calling asynchronous code in a constructor, maby [this reply](https://stackoverflow.com/questions/23048285/call-asynchronous-method-in-constructor/34311951#34311951) to a similar scenario could help? – Shazi Nov 18 '18 at 22:07

2 Answers2

2

Since you are doing this in the constructor , I would try the following:

using System.Threading.Tasks;

The risk here is if you are not in control of the LoadThings completing, it can hang.

public MonitoringViewModel()
{
    var task = Task.Run(async () => { await LoadThings();}
    Task.WaitAll(task); //block and wait for task to complete
fradsham
  • 81
  • 1
  • 5
  • Why `Task.WaitAll`? – Paulo Morgado Nov 18 '18 at 23:39
  • Thank you very much, after many days fighting with this, your answer is the only thing that has worked for me, although I am concerned about the risk you are aiming at, could I please give some more reference on this and / or explain it in a little more detail? – lavilaso Nov 18 '18 at 23:52
  • Task.WaitAll is just what Microsoft called it (may not be the best name), but basically it waits for all of the provided tasks to complete execution. You can pass it a single task (as I done above) or an array of tasks, but it will block any further progress until the associated task(s) have ended. – fradsham Nov 19 '18 at 16:32
  • Thanks, do you have any examples of how to do this with an exception control and timeout to control a time limit of completion of the task? – lavilaso Nov 21 '18 at 17:45
1
public async Task<List<PcThing>> LoadThings()
{
    return await App.WebApiManager.GetCustomerThinksAsync();
}

And in your ViewModel

Things = LoadThings().GetAwaiter().GetResult();
Bruno Caceiro
  • 6,179
  • 1
  • 19
  • 37
  • Thanks, although it does not work, I just tried it and I get the same result as when I tried to use App.ApiManager.GetCustomerThinksAsync (). Result, which is that the green signal in the xamarin live player never disappears and never starts the app and verifies With the breakpoints the app never executes the GetCutomerThinks method, I get to see the flow on it but the breakpoints within it are never reached. Any ideas ? – lavilaso Nov 18 '18 at 21:29