Task.ContinueWith()未按预期执行

3
我正在尝试使用async/await和使用ContinueWith()链接Tasks并检查TaskContinuationOptions.NotOnFaulted异常的代码重写我的一些旧代码。
当我调试代码时,我注意到它没有按照我预期的那样运行。两个webrequest都成功了,但是只有第一个continuation处理了响应。
第二个continuation未完成,最后一个continuation给出了结果:
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
如果有更好的方法可以不写一堆笨拙的方法来完成吗?请使用async/await。 - Sriram Sakthivel
1
你不需要使用ContinueWith去处理正在等待的任务,那正是这种语法的全部意义所在。只需等待任务完成或失败,然后await之后的代码将会执行。你可以通过正在等待的方法返回的值提取结果,例如 var result = await api.MakeRequest(... 。你可以使用标准的try/catch语法来处理异常。 - Ben Robinson
是的,那很有道理。但是如果我想并行处理订单而不等待任务呢? - Timo1995
1个回答

1

就像@Ben Robinson所说的那样,使用await会自动将方法的其余部分注册为一个续体,只有在操作成功时才执行,否则会抛出异常。我会更改我的方法以删除ContinueWith调用,并考虑在异步操作完成后不需要返回到当前SynchrionizationContext的情况下使用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);

但是为什么第二个.ContinueWith中的await后面的代码没有执行呢? - tonlika

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接