【问题标题】:Async JSON Deserialization异步 JSON 反序列化
【发布时间】:2014-07-29 12:02:34
【问题描述】:

我需要做一个 RestRequest 并获取一些 JSON,我不确定我的方法是否真的是异步的,因为当我使用这个方法时,我的 UI 仍然有一点冻结。

 public async Task<List<MyObject>> Load() 
            {
                var tcs = new TaskCompletionSource<List<Myobject>>();
                var client = new RestSharp.RestClient("https://exampleapi.com");
                client.Authenticator = OAuth1Authenticator.ForProtectedResource(
           [...]);
                var request = new RestSharp.RestRequest("examp.json", Method.GET);
                client.ExecuteAsync(request, response =>
                {
                    if (response.StatusCode == HttpStatusCode.OK)
                    {
                        List_ = new List<MyObject>();
                        List_ = JsonConvert.DeserializeObject<List<MyObject>>(response.Content);
                        tcs.SetResult(List_);
                    }
                    else
                    {
                        MessageBox.Show("Error");
                    }
                });
                return await tcs.Task;        
            }

专门针对这行代码:

List_ = JsonConvert.DeserializeObject<List<MyObject>>(response.Content);

真的是异步的吗?因为它似乎挡住了 UI。你能告诉我如何使这个函数正确异步吗?

【问题讨论】:

标签: c# .net json windows-phone-8 asynchronous


【解决方案1】:

似乎作为参数传递给ExecuteAsync 的委托正在UI 线程上执行。如果是这种情况,只需使用Task.Run 在线程池上运行委托即可。

client.ExecuteAsync(request, async (response) =>
    {
        if (response.StatusCode == HttpStatusCode.OK)
        {
            var list = await Task.Run( () => JsonConvert.DeserializeObject<List<MyObject>>(response.Content));
            tcs.SetResult(list);
        }
        else
        {
            MessageBox.Show("Error");
        }
    });

List_ 是一个字段吗?在我看来,它应该是一个局部变量。此外,在反序列化 json 之前,无需使用空列表对其进行初始化。

【讨论】:

  • 谢谢 我也删除了我的List的初始化,一般我怎么知道我的UI线程上是否执行了操作?
  • @user2505650 老实说,我对 Windows Phone API 了解不多,但这里有一个简单的测试:添加 Thread.Sleep(5000) 并运行代码 - 如果它阻塞了 UI,那么它正在在 UI 线程上运行。
【解决方案2】:

JsonConvert.DeserializeObject 是同步的。您可以通过它立即返回其计算结果的事实告诉您。它不可能“在后台”做某事,然后才把结果交给你。

使用 Task.Run 将 CPU 绑定工作移至线程池线程。如果对您更方便,您可以将整个 REST 请求移到那里。

请注意,您的消息框调用应该在 UI 线程上运行。最好不要像现在这样在线程池线程上创建消息框。这将导致两个 UI 线程。消息框不会是模态的。

【讨论】:

  • 谢谢,我会更改我的MessageBox,但是我如何判断操作是否在UI线程上执行?
  • 这通常被记录在案。我确定 RestSharp 记录了回调将被调用的线程。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2023-01-09
  • 1970-01-01
  • 2016-07-22
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-22
相关资源
最近更新 更多