Ожидание результата асинхронного метода с использованием Task & lt; T & gt; .Result () [duplicate]

Мы можем использовать класс JSONObject для преобразования строки JSON в объект JSON и итерации по объекту JSON. Используйте следующий код.

JSONObject jObj = new JSONObject(contents.trim());
Iterator<?> keys = jObj.keys();

while( keys.hasNext() ) {
  String key = (String)keys.next();
  if ( jObj.get(key) instanceof JSONObject ) {           
    System.out.println(jObj.getString(String key));
  }
}
75
задан julio.g 10 July 2014 в 13:25
поделиться

2 ответа

Здесь уже есть некоторые хорошие ответы / комментарии, но просто для прослушивания ...

Есть две причины, по которым я предпочитаю await по сравнению с Result (или Wait). Во-первых, обработка ошибок отличается; await не завершает исключение в AggregateException. В идеале, асинхронный код никогда не должен иметь дело с AggregateException вообще, если только он специально не хочет .

Вторая причина немного более тонкая. Как я описываю в своем блоге (и в книге), Result / Wait может вызвать взаимоблокировки , а может вызвать еще более тонкие взаимоблокировки при использовании в методе async . Поэтому, когда я читаю код, и вижу Result или Wait, это флаг немедленного предупреждения. Result / Wait является правильным, если вы абсолютно уверены , что задача уже завершена. Мало того, что это трудно увидеть с первого взгляда (в коде реального мира), но он также более хрупкий для изменения кода.

Это не значит, что Result / Wait должен никогда . Я следую этим рекомендациям в своем собственном коде:

  1. Асинхронный код в приложении может использовать только await.
  2. Асинхронный код утилиты (в библиотеке) может иногда использовать Result / Wait, если код действительно вызывает его.
  3. Параллельный код задачи может использовать Result и Wait.

Обратите внимание, что (1) на сегодняшний день является распространенным явлением, поэтому моя тенденция использовать await повсюду и рассматривать другие случаи как исключения общего правила.

99
ответ дан Stephen Cleary 27 August 2018 в 18:44
поделиться

Это имеет смысл, если timeoutTask является произведением Task.Delay, которое я считаю тем, что есть в книге.

Task.WhenAny возвращает Task<Task>, где внутренняя задача является одной из тех, которые вы передали в качестве аргументов. Его можно было бы переписать следующим образом:

Task<Task> anyTask = Task.WhenAny(downloadTask, timeoutTask);
await anyTask;
if (anyTask.Result == timeoutTask)  
  return null;  
return downloadTask.Result; 

В любом случае, поскольку downloadTask уже завершен, между return await downloadTask и return downloadTask.Result существует очень незначительная разница. Именно в этом будет бросок AggregateException, который обертывает любое исходное исключение, как указано в комментариях @KirillShlenskiy. Первый будет просто перебрасывать исходное исключение.

В любом случае, где бы вы ни обрабатывали исключения, вы должны в любом случае проверить наличие AggregateException и его внутренних исключений, чтобы получить причину ошибки.

7
ответ дан Noseratio 27 August 2018 в 18:44
поделиться
Другие вопросы по тегам:

Похожие вопросы: