在我的MvvmCross / Xamarin Core上,我想从网上获取一些json feed并将其反序列化为各种对象类型。为此,我开发了一个通用类:
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);
}
}
我在核心服务上这样称呼它 - 结果绑定到我的UI:
public void GetFamilies(Action<IEnumerable<FamilyDTO>> onAction)
{
onAction.Invoke(JsonDeserializerT<FamilyDTO>.DeserializeList("family").Result);
}
但我的用户界面没有任何反应......
但是,此代码有效:
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);
}
因为我有10个方法(对于5种对象类型),我认为泛型是最好的模式。
不会抛出异常。 跟踪,我:
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).
我试过了:
添加“ConfigureAwait(false)”。 HttpClient not throwing exception when using await on GetAsync / http://blog.stephencleary.com/2012/07/dont-block-on-async-code.html
删除GetAsync的“等待”(并添加“结果”。)
答案 0 :(得分:1)
我已经解决了我的问题。 我使用async / await关键字在异步方法中更改了我的方法:
public async void GetFamilies(Action<IEnumerable<FamilyDTO>> onAction)
{
onAction.Invoke(await JsonDeserializerT<FamilyDTO>.DeserializeList("family"));
}
答案 1 :(得分:1)
使用Result
,您导致死锁,我会详细解释on my blog和in an MSDN article。总之,async
方法正在尝试在UI线程上恢复,但对Result
的调用阻止了UI线程。
最佳解决方案是制作调用方法async
并使用await
代替Result
。如果您正在进行异步编程,则应遵循Task-based Asynchronous Pattern中记录的准则。我还建议您返回结果而不是调用回调。回调是如此2010年。
public Task<IEnumerable<FamilyDTO>> GetFamiliesAsync()
{
return JsonDeserializerT<FamilyDTO>.DeserializeListAsync("family");
}