2014-08-27 2 views
1

Im пытается переписать часть моего старого кода, используя async/wait и chaining Задачи, использующие ContinueWith() и проверку исключений с помощью TaskContinuationOptions.NotOnFaulted.Task.ContinueWith() не выполняется, как ожидалось

Когда я отлаживаю код, я заметил, что он не работает, как я ожидал. Оба веб-запроса успешны, но только первое продолжение обрабатывает ответ.

Второе продолжение не завершает и последний дает мне результат:

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 –

+1

Вам не нужно ContinueWith задачи вы ожидающая, что вся суть синтаксиса , Просто ждите задания, а затем код после ожидания будет выполняться только после завершения или неудачной задачи. Вы извлекаете результат из значения, возвращаемого методом, который вы ожидаете, например. 'var result = await api.MakeRequest (...'. Вы можете использовать стандартный синтаксис try/catch для обработки исключений. –

+0

Да, это имеет смысл. Но что, если я хочу обрабатывать заказы параллельно и не ждать задачи? – Timo1995

ответ

1

Как @Ben Робинсон сказал, что использование await автоматически регистрирует остальную часть метода, как продолжение, которое выполняется только в случае, если операция прошла успешно, в противном случае генерируется исключение. Я бы изменил свой метод, чтобы удалить вызовы ContinueWith и подумать об использовании ConfigureAwait(false), если вам не нужно возвращаться к текущему SynchrionizationContext после завершения асинхронных операций, то есть остальная часть метода продолжит выполнение в потоке пула потоков. Вы также можете найти 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

Но почему код не после ожидания во втором .ContinueWith выполняется? – tonlika