سؤال

On my MvvmCross/Xamarin Core, I want to get some json feed from the web and deserialize it to various object types. To do this, I developped a generic class:

public static class JsonDeserializerT<T>
{
    private const string BaseUrl = "http://www.mywebsite.com/json/";
    public static async Task<List<T>> DeserializeList(string url)
    {
        url = BaseUrl + url;
        var httpClient = new HttpClient();
        var response = await httpClient.GetAsync(new Uri(url));
        // hanging here 
        response.EnsureSuccessStatusCode();
        var jsonContent = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<List<T>>(jsonContent);
    }

    public static async Task<T> DeserializeItem(string url)
    {
        url = BaseUrl + url;
        var httpClient = new HttpClient();
        var response =
            await httpClient.GetAsync(new Uri(url));
        // hanging here 
        response.EnsureSuccessStatusCode();
        var jsonContent = await response.Content.ReadAsStringAsync();
        return JsonConvert.DeserializeObject<T>(jsonContent);
    }
}

And I call it like this on a Core Service - result is binded to my UI:

public void GetFamilies(Action<IEnumerable<FamilyDTO>> onAction)
{
    onAction.Invoke(JsonDeserializerT<FamilyDTO>.DeserializeList("family").Result);
}

But nothing happens on my UI...

However, this code works :

public void GetFamilies(Action<IEnumerable<FamilyDTO>> onAction)
{
    url = BaseUrl + url;
    var httpClient = new HttpClient();
    var response = await httpClient.GetAsync(new Uri(url));
    response.EnsureSuccessStatusCode();
    var jsonContent = await response.Content.ReadAsStringAsync();
    var d = JsonConvert.DeserializeObject<List<FamilyDTO>>(jsonContent);
    onAction.Invoke(d);
}

Because I have 10 methods (for 5 object types), I have thought that generic was the best pattern.

No exception is thrown. On trace, I've :

mvx:Diagnostic:  1,09 Showing ViewModel FamiliesViewModel
'TaskHost.exe' (CoreCLR: Silverlight AppDomain) : Chargé 'C:\Data\Programs\{9AE43B06-7CA4-4BA9-A545-12773FB5C841}\Install\system.windows.interactivity.DLL'. Impossible de trouver ou d'ouvrir le fichier PDB.
'TaskHost.exe' (CoreCLR: Silverlight AppDomain) : Chargé 'C:\Data\Programs\{9AE43B06-7CA4-4BA9-A545-12773FB5C841}\Install\Newtonsoft.Json.DLL'. Impossible de trouver ou d'ouvrir le fichier PDB.
'TaskHost.exe' (CoreCLR: Silverlight AppDomain) : Chargé 'C:\Data\Programs\{9AE43B06-7CA4-4BA9-A545-12773FB5C841}\Install\System.Net.Http.Primitives.DLL'. Impossible de trouver ou d'ouvrir le fichier PDB.
Le thread 0xe30 s'est arrêté avec le code 259 (0x103).
Le thread 0xe44 s'est arrêté avec le code 259 (0x103).
Le thread 0xe4c s'est arrêté avec le code 259 (0x103).
Le thread 0xe68 s'est arrêté avec le code 259 (0x103).
Le thread 0xe78 s'est arrêté avec le code 259 (0x103).
Le thread 0xe84 s'est arrêté avec le code 259 (0x103).
Le thread 0xea4 s'est arrêté avec le code 259 (0x103).
Le thread 0xed0 s'est arrêté avec le code 259 (0x103).
Le thread 0xed8 s'est arrêté avec le code 259 (0x103).
Le thread 0xee0 s'est arrêté avec le code 259 (0x103).
Le thread 0xee8 s'est arrêté avec le code 259 (0x103).
Le thread 0xef4 s'est arrêté avec le code 259 (0x103).
Le thread 0xf04 s'est arrêté avec le code 259 (0x103).
Le thread 0xf30 s'est arrêté avec le code 259 (0x103).
Le thread 0xf44 s'est arrêté avec le code 259 (0x103).
Le thread 0xf4c s'est arrêté avec le code 259 (0x103).
Le thread 0xf60 s'est arrêté avec le code 259 (0x103).
Le thread 0xf74 s'est arrêté avec le code 259 (0x103).
Le thread 0xf90 s'est arrêté avec le code 259 (0x103).
Le thread 0xf9c s'est arrêté avec le code 259 (0x103).
Le thread 0xfa4 s'est arrêté avec le code 259 (0x103).
Le thread 0xfb8 s'est arrêté avec le code 259 (0x103).
Le thread 0xfc4 s'est arrêté avec le code 259 (0x103).
Le thread 0xfd0 s'est arrêté avec le code 259 (0x103).
Le thread 0xfe0 s'est arrêté avec le code 259 (0x103).
Le thread 0xff0 s'est arrêté avec le code 259 (0x103).
Le thread 0xffc s'est arrêté avec le code 259 (0x103).
Le thread 0x804 s'est arrêté avec le code 259 (0x103).
Le thread 0x350 s'est arrêté avec le code 259 (0x103).

I tried:

هل كانت مفيدة؟

المحلول

I've solved my problem. I changed my method in an asynchronous method with async / await keywords:

public async void GetFamilies(Action<IEnumerable<FamilyDTO>> onAction)
{
    onAction.Invoke(await JsonDeserializerT<FamilyDTO>.DeserializeList("family"));
}

نصائح أخرى

By using Result, you're causing a deadlock that I explain in detail on my blog and in an MSDN article. In summary, the async method is attempting to resume on the UI thread, but the call to Result is blocking the UI thread.

The best solution is to make your calling method async and use await instead of Result. If you're doing asynchronous programming, you should be following the guidelines documented in the Task-based Asynchronous Pattern. I also recommend that you return the results instead of invoking a callback. Callbacks are so 2010.

public Task<IEnumerable<FamilyDTO>> GetFamiliesAsync()
{
  return JsonDeserializerT<FamilyDTO>.DeserializeListAsync("family");
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top