2014-08-29 65 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

相關問題