2014-08-27 104 views
1

我試圖用異步/等待和使用ContinueWith()重新編寫一些舊代碼並檢查TaskContinuationOptions.NotOnFaulted的異常。Task.ContinueWith()未按預期方式執行

當我調試代碼時,我注意到它沒有像我期望的那樣運行。 兩個webrequests都成功,但只有第一個連續處理響應。

第二延續未完成 ,最後一個給我的結果:

Id = 1, Status = RanToCompletion, Method = "{null}", Result = "System.Threading.Tasks.Task`1[System.Threading.Tasks.VoidTaskResult]" 

和結果:

Id = 2, Status = WaitingForActivation, Method = "{null}", Result = "{Not yet computed}" 

我的問題是什麼我做錯了,我能這樣做第二次繼續完成。 如果使用ContinueWith將任務鏈接在一起被認爲是一種很好的做法,或者如果有更好的方法可以在不編寫一堆笨拙的方法的情況下做到這一點,我也會感興趣嗎?說 感謝您的幫助

using Newtonsoft.Json.Linq;     

    var api = new Api(); 
    var order = new Dictionary<string, object>(); 
    await api.MakeRequest(Api.Endpoint.Orders, HttpMethod.Get, null, "?completed=false&page=" + count) 
    //Look for new Orders 
    .ContinueWith(ant => 
    { 
      dynamic jsonOrder = JObject.Parse(ant.Result); 
      JArray data = jsonOrder.data; 
      //Process Json Response 
      order.Add("customer_name", (string)data[j]["customer_name"]); 
      order.Add("product_id", (string)data[j]["product_id"]); 
      order.Add("order_id", (string)data[j]["order_id"]); 
      order.Add("timestamp", (int)data[j]["timestamp"]); 
      //Entries are successfully added 
    }, TaskContinuationOptions.NotOnFaulted) 
    //Now get more details about the product 
    .ContinueWith(async (ant) => 
    { 
      string result = await api.MakeRequest(Api.Endpoint.Product, HttpMethod.Get, null, (string)order["product_id"]); 
      //The Request succeeds 

      //This code block does not execute 
      dynamic json = JObject.Parse(result); 
      order.Add("deadline", (int)json.data.deadline); 
      order.Add("price", (string)json.data.price); 
      order.Add("amount", (int)json.data.amount); 
      //This code block does not execute 

    }, TaskContinuationOptions.NotOnFaulted) 
    //Get some more details about the Customer (isRecurring? etc) 
    .ContinueWith(async (ant) => 
    { 
     //Some more code here 
    } 
+1

*如果有更好的方式來做到這一點,而無需編寫一串笨拙的方法是什麼?*使用異步/ AWAIT – 2014-08-27 09:14:30

+1

你並不需要ContinueWith你正在等待一個任務,那就是整個的語法點。只需等待任務,然後等待後的代碼將只在任務完成或失敗時執行。您從您正在等待的方法返回的值中提取結果,例如var result = await api.MakeRequest(...'。你可以使用標準的try/catch語法來處理異常。 – 2014-08-27 09:24:00

+0

是的,這是有道理的。但是如果我想並行處理並不等待任務呢? – Timo1995 2014-08-27 09:49:51

回答

1

像@Ben羅賓遜利用await自動註冊方法作爲如果操作成功時,纔會執行一個延續的休息,否則會拋出異常。如果在異步操作完成後您不需要返回到當前的SynchrionizationContext,即,該方法的其餘部分將繼續在線程池線程上執行,我會更改我的方法以刪除ContinueWith調用並考慮使用ConfigureAwait(false)。您也可能會發現this article有用。

var api = new Api(); 
var order = new Dictionary<string, object>(); 

await api.MakeRequest(Api.Endpoint.Orders, HttpMethod.Get, null, "?completed=false&page=" + count).ConfiugureAwait(false); 

//Look for new Orders 
dynamic jsonOrder = JObject.Parse(ant.Result); 
JArray data = jsonOrder.data; 
//Process Json Response 
order.Add("customer_name", (string)data[j]["customer_name"]); 
order.Add("product_id", (string)data[j]["product_id"]); 
order.Add("order_id", (string)data[j]["order_id"]); 
order.Add("timestamp", (int)data[j]["timestamp"]); 

//Now get more details about the product 
string result = await api.MakeRequest(Api.Endpoint.Product, HttpMethod.Get, null, (string)order["product_id"]).ConfiugureAwait(false); 

dynamic json = JObject.Parse(result); 
order.Add("deadline", (int)json.data.deadline); 
order.Add("price", (string)json.data.price); 
order.Add("amount", (int)json.data.amount); 
+0

但是爲什麼代碼在第二個之後沒有等待?繼續執行? – tonlika 2018-03-10 10:48:42