2016-04-22 73 views
1

我想通过HttpClient进行异步调用以从RESTful WCF服务加载数据。该代码位于Xamarin UI中使用的可移植类库(PCL)中。看起来,异步调用从未被解雇。我已经阅读了关于这方面问题的博客,我相信我已经解决了这些问题。异步调用永不开启

我从做如下一个客户端的数据仓库类呼叫:

public MyRepository() 
    { 
     Task.Run(async() => { await LoadDataAsync(url); }); 
    } 
    public async Task LoadDataAsync(string uri) 
    { 
     if (allRecords != null) **// Breakpoint here never hit.** 
     { 
      string responseJsonString = null; 

      using (var httpClient = new HttpClient()) 
      { 
       try 
       { 
        Task<HttpResponseMessage> getResponse = httpClient.GetAsync(uri); 
        HttpResponseMessage response = await getResponse; 
        responseJsonString = await response.Content.ReadAsStringAsync(); 
        myList = JsonConvert.DeserializeObject<List<MyListItem>>(responseJsonString); 
       } 
       catch (Exception ex) 
       { 

       } 
      } 
     } 
    } 

任何帮助非常赞赏。提前致谢。

+0

你真的不应该做一个空的catch(Exception ex)',你只是隐藏了很难诊断错误的错误。 –

+0

你可以在桌面.NET上重现这一点吗? –

回答

-2

为什么它不会触发:可能是因为您的应用程序正在退出之前,您打算通过Task.Run启动的线程可能实际启动。

为了检验上述理论,放了Thread.Sleep调用之后(这不是解决办法,但测试):

public MyRepository() 
{ 
    Task.Run(async() => { await LoadDataAsync(url); }); 
    System.Threading.Thread.Sleep(10000); //will sleep for 10 seconds 
} 

不管怎么说,采取异步方法的好处是在你一起去除Task.Run,​​直接调用函数上的等待函数,线程在等待运行之后会产生允许执行其他事情的“getresponse”对象,直到您实际需要等待它,当您实际需要等待时它,然后等待。

+0

downvote的任何理由? –

2

如果我是你,我会避免调用构造函数里面异步方法..

,做这样的事情

(创建一个返回类的实例的静态方法)

const string uri = "https://www.webservice.com/api/getdata"; 
    private List<MyListItem> myList; 

    public static async Task<MyRepository> GetMyRepository() 
    { 
     MyRepository myRepository = new MyRepository(); 
     await myRepository.LoadDataAsync(uri); 

     return myRepository; 
    } 

    public MyRepository() 
    { 
    } 

    public async Task LoadDataAsync(string uri) 
    { 
     if (allRecords != null) **// Breakpoint here never hit.** 
     { 
      string responseJsonString = null; 

      using (var httpClient = new HttpClient()) 
      { 
       try 
       { 
        Task<HttpResponseMessage> getResponse = httpClient.GetAsync(uri); 
        HttpResponseMessage response = await getResponse; 
        responseJsonString = await response.Content.ReadAsStringAsync(); 
        myList = JsonConvert.DeserializeObject<List<MyListItem>>(responseJsonString); 
       } 
       catch (Exception ex) 
       { 

       } 
      } 
     } 
    } 

我无法解释你为什么遇到这个问题,但也许这可能会帮助你。

+0

这是一个很好的解决方案,但是我要做的一个改变是现在你有一个静态工厂方法,使构造函数是私人的,所以只有工厂方法可以新建实例。 –

+0

是的,它应该转换为线程安全的单例类。 –

0

问题是,您在构造函数中调用“即发即弃”异步调用。这应该避免的是,我们发现您的代码不会被调用的原因 - 当它可能是......我建议做以下修改:

public async Task LoadDataAsync(string uri) 
{ 
    if (allRecords != null) **// Breakpoint here never hit.** 
    { 
     string responseJsonString = null; 

     using (var httpClient = new HttpClient()) 
     { 
      try 
      { 
       Task<HttpResponseMessage> getResponse = httpClient.GetAsync(uri); 
       HttpResponseMessage response = await getResponse; 
       responseJsonString = await response.Content.ReadAsStringAsync(); 
       myList = JsonConvert.DeserializeObject<List<MyListItem>>(responseJsonString); 
      } 
      catch (Exception ex) 
      { 

      } 
     } 
    } 
} 

注意如何居然没有任何变化,除了一起去除构造函数。当这个对象被实例化时 - 只需等待调用LoadDataAsync函数。

public async Task SomeConsumerOfYourObject() 
{ 
    var wcfObj = new YourWcfObject(); 
    await wcfObj.LoadDataAsync(this.Uri); 

    // Then you're good... 
}