2014-08-29 68 views
1

我是C#的新手,我想在Windows Phone应用程序中为我的RESTlike API创建库。UploadStringAsync在Windows Phone 8中不起作用

我的API结构是有点

http://mysiteurl/api/method_name.json 

所以我想打电话与(METHOD_NAME,则params)API,并返回指定的类。

当我在Windows Phone 8.1程序冻结时启动此代码并且什么也没有发生。我还可以看到在服务器端的东西(任何呼叫)

API.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Net; 
using System.Text; 
using System.Diagnostics; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 
using SampleProg.Model; 

namespace SampleProg.Lib 
{ 
    public class Api 
    { 
     public async Task<VersionClass> versionInfo() 
     { 
      Debug.WriteLine("versionInfo()"); 
      var result = await this.Post<VersionClass>("version", "{}", null); 
      Debug.WriteLine(result); 
      return result; 
     } 

     public async Task<TReturnType> Post<TReturnType>(string methodName, string data, Dictionary<string, string> headers) 
     { 
      var webClient = new WebClient(); 

      webClient.Headers["Content-Type"] = "application/json"; 
      webClient.Encoding = Encoding.UTF8; 

      var uri = new Uri(String.Format("http://mysiteurl/api/{0}.json", methodName)); 

      if (headers != null) 
      { 
       foreach (var key in headers.Keys) 
       { 
        webClient.Headers[key] = headers[key]; 
       } 
      } 

      return await Post<TReturnType>(webClient, uri, data); 
     } 

     private async Task<TReturnType> Post<TReturnType>(WebClient webClient, Uri uri, string jsonData) 
     { 
      TReturnType returnObject = default(TReturnType); 

      var taskCompletionSource = new TaskCompletionSource<TReturnType>(); 

      webClient.UploadStringCompleted += (s, e) => 
      { 
       var result = e.Result; 

       try 
       { 
        Debug.WriteLine(result); 
        returnObject = JsonConvert.DeserializeObject<TReturnType>(result); 

        taskCompletionSource.SetResult(returnObject); 
       } 
       catch (Exception ex) 
       { 
        var newEx = new Exception(
         string.Format("Failed to deserialize server response: {0}", result), ex); 
        taskCompletionSource.SetException(newEx); 
       } 
      }; 

      webClient.UploadStringAsync(uri, "POST", jsonData); 

      return await taskCompletionSource.Task; 
     } 

    } 
} 

App.xaml.cs(我称之为公共应用程序(){}):

var api = new Api(); 
var apiTask = api.versionInfo(); 
VersionClass version = (VersionClass)apiTask.Result; 
Debug.WriteLine(version.num); 

VersionClass.cs:

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Diagnostics; 
using System.Threading.Tasks; 
using Newtonsoft.Json; 

namespace SampleProg.Model 
{ 
    public class VersionClass 
    { 
     [JsonProperty("version")] 
     public int num { get; set; } 

    } 
} 

你能告诉我什么是错?我用这个代码(在底部)http://sandor68.rssing.com/chan-11557297/all_p1.html为基础

+1

您可以使用[UploadStringTaskAsync(HTTP:// MSDN .microsoft.com/en-us/library/hh193920(v = vs.110).aspx)而不是'UploadStringAsync'?我也猜你是死锁,因为你在你的任务上调用'.Result'而不是等待它。 – 2014-08-29 15:19:15

回答

1

此:

VersionClass version = (VersionClass) apiTask.Result; 

是死锁您的应用程序。

发生了什么是SynchronizationContext正在尝试将管制员控制回之后的await内部方法。

你应该始终await上一个Task

VersionClass version = (VersionClass) await apiTask; 

而且,要知道,你的UploadStringAsync包装返回一个Task已经取得了您通过WebClient.UploadStringTaskAsync

开箱即用的编辑

如果您选择继续您的Post [R版本,你不应该await对返回Task,你应该让用户做到这一点,并注销从UploadStringCompleted处理程序:

private async Task<TReturnType> Post<TReturnType>(WebClient webClient, Uri uri, string jsonData) 
{ 
    TReturnType returnObject = default(TReturnType); 

    var taskCompletionSource = new TaskCompletionSource<TReturnType>(); 

    UploadStringCompletedEventHandler handler = null; 
    handler = (s, e) => 
    { 
     webClient.UploadStringCompleted -= handler; 

     var result = e.Result; 

     try 
     { 
      Debug.WriteLine(result); 
      returnObject = JsonConvert.DeserializeObject<TReturnType>(result); 

      taskCompletionSource.SetResult(returnObject); 
     } 
     catch (Exception ex) 
     { 
      var newEx = new Exception(
       string.Format("Failed to deserialize server response: {0}", result), ex); 
      taskCompletionSource.SetException(newEx); 
     } 
    }; 

    webClient.UploadStringCompleted += handler; 

    webClient.UploadStringAsync(uri, "POST", jsonData); 

    return taskCompletionSource.Task; 
} 
+0

Int以这种方式如何正确取消注册处理程序?我得到了“无法将匿名方法分配给隐式类型的局部变量”。错误,如果我尝试像在示例代码中那样做。 – 2014-09-03 17:28:01

+0

@Mikhail我修复了我的代码。现在应该工作。 – 2014-09-03 18:08:53

相关问题