Вот простой способ отличить два списка (независимо от содержимого), вы можете получить результат, как показано ниже:
>>> from sets import Set
>>>
>>> l1 = ['xvda', False, 'xvdbb', 12, 'xvdbc']
>>> l2 = ['xvda', 'xvdbb', 'xvdbc', 'xvdbd', None]
>>>
>>> Set(l1).symmetric_difference(Set(l2))
Set([False, 'xvdbd', None, 12])
Надеюсь, это поможет.
Выполняя иначе простой метод «thunk», async создает в памяти состояние async state machine, а не async - нет. Хотя это часто может указывать на использование версии non-async, поскольку она более эффективна (это правда), это также означает, что в случае зависания у вас нет доказательств того, что этот метод задействован в «стеке возврата / продолжения», что иногда затрудняет понимание повесы.
Итак, да, когда perf не критичен (и обычно это не так), я брошу async на все эти методы thunk, чтобы у меня была машина состояния async, чтобы помочь мне диагностировать зависания позже, и также, чтобы гарантировать, что, если эти методы thunk когда-либо будут развиваться со временем, они обязательно вернут сбитые задачи вместо throw.
Это также смущает меня, и я чувствую, что предыдущие ответы не учитывали ваш фактический вопрос:
Зачем использовать конструкцию return wait, когда вы можете напрямую возвращать задачу из внутреннего вызова DoAnotherThingAsync ()?
blockquote>Ну, иногда вы на самом деле хотите
Task<SomeType>
, но в большинстве случаев вам действительно нужен экземплярSomeType
, то есть результат задачи.Из вашего кода:
async Task<SomeResult> DoSomethingAsync() { using (var foo = new Foo()) { return await foo.DoAnotherThingAsync(); } }
Человек, незнакомый с синтаксисом (например, я), может подумать, что этот метод должен возвращать
Task<SomeResult>
, но поскольку он помечен какasync
, это означает, что его фактический тип возвратаSomeResult
. Если вы просто используетеreturn foo.DoAnotherThingAsync()
, вы возвращаете задачу, которая не будет компилироваться. Правильный способ - вернуть результат задачи, поэтомуreturn await
.
var task = DoSomethingAsync();
вы получите задание, а не T
– Shoe
5 January 2017 в 18:50
async/await
. Насколько я понимаю, Task task = DoSomethingAsync()
, в то время как Something something = await DoSomethingAsync()
работают. Первая дает вам правильную задачу, а вторая из-за ключевого слова await
дает результат result i> из задачи после ее завершения. Я мог бы, например, иметь Task task = DoSomethingAsync(); Something something = await task;
.
– heltonbiker
5 January 2017 в 19:51
Единственная причина, по которой вы захотите это сделать, - это если в предыдущем коде есть еще один await
или если вы каким-то образом обработаете результат перед его возвратом. Другой способ, которым это может происходить, - это try/catch
, который изменяет порядок обработки исключений. Если вы ничего не делаете, тогда вы правы, нет причин добавлять накладные расходы на создание метода async
.
return await
необходимо (вместо того, чтобы просто возвращать задачу вызова ребенка) , даже если в более раннем коде есть еще один ожидание. Не могли бы вы предоставить объяснение?
– TX_
30 September 2013 в 17:33
async
, то как бы вы ожидали первой задачи? Вам нужно отметить метод как async
, если вы хотите использовать any i>. Если метод отмечен как async
, и у вас есть await
ранее в коде, тогда вам нужно await
выполнить вторую операцию async для правильного типа. Если вы просто удалили await
, тогда он не будет компилироваться, так как возвращаемое значение не будет иметь правильный тип. Поскольку метод async
, результат всегда завернут в задачу.
– Servy
30 September 2013 в 17:38
async
вы не возвращаете задачу, вы возвращаете результат задачи, которая затем будет завернута.
– Servy
30 September 2013 в 20:21
Task<Type>
явно, а async
диктует возвратить Type
(который сам компилятор превратится в Task<Type>
).
– Noseratio
30 September 2013 в 20:33
async
является просто синтаксическим сахаром для явной проводки продолжений. Вы не нуждаетесь i> async
, чтобы что-либо сделать, но при выполнении практически нетривиальной асинхронной операции с резко i> легче работать. Например, код, который вы предоставили, на самом деле не распространяет ошибки, как вы этого хотели, и сделать это правильно в еще более сложных ситуациях становится намного сложнее. В то время как вы никогда не нуждаетесь i> async
, ситуации, которые я описываю, это то, где он добавляет ценность, чтобы использовать его.
– Servy
26 February 2016 в 03:33
Если вам не нужно async
(т. е. вы можете напрямую вернуть Task
), тогда не используйте async
.
Есть ситуации, когда return await
полезно, например, если у вас есть две асинхронные операции :
var intermediate = await FirstAsync();
return await SecondAwait(intermediate);
Дополнительные сведения о производительности async
см. в статье MSDN Стивена Тоуба и video по этой теме.
Обновление: я написал сообщение в блоге , которое идет гораздо подробнее.
await
полезен во втором случае? Почему бы не сделать return SecondAwait(intermediate);
?
– Matt Smith
30 September 2013 в 17:15
return SecondAwait(intermediate);
достичь цели в этом случае? Я думаю, return await
здесь лишний ...
– TX_
30 September 2013 в 17:31
await
в первой строке, вы должны использовать его и во втором.
– svick
30 September 2013 в 21:29
async
будет использовать ресурсы SecondAwait
является строкой, сообщение об ошибке: «CS4016: Поскольку это метод асинхронизации, выражение возврата должно быть type 'string' вместо 'Task & lt; string & gt;' & quot ;.
– svick
23 November 2016 в 13:17
Есть один подлый случай, когда return
в обычном методе и return await
в async
метод ведут себя по-разному: в сочетании с using
(или, более общо, любой return await
в блоке try
), .
Рассмотрим эти две версии метода:
Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return foo.DoAnotherThingAsync();
}
}
async Task<SomeResult> DoSomethingAsync()
{
using (var foo = new Foo())
{
return await foo.DoAnotherThingAsync();
}
}
Первый метод будет Dispose()
объектом Foo
, как только метод DoAnotherThingAsync()
вернется, что вероятно, задолго до его завершения. Это означает, что первая версия, вероятно, глючит (потому что Foo
находится слишком рано), а вторая версия будет работать нормально.
foo.DoAnotherThingAsync().ContinueWith(_ => foo.Dispose());
– ghord
23 September 2014 в 09:58
Dispose()
возвращает void
. Вам понадобится что-то вроде return foo.DoAnotherThingAsync().ContinueWith(t -> { foo.Dispose(); return t.Result; });
. Но я не знаю, почему бы вам это сделать, когда вы можете использовать второй вариант.
– svick
23 September 2014 в 10:05
{ var task = DoAnotherThingAsync(); task.ContinueWith(_ => foo.Dispose()); return task; }
. Вариант использования довольно прост: если вы используете .NET 4.0 (как и большинство), вы все равно можете написать асинхронный код таким образом, который будет хорошо работать из 4.5 приложений.
– ghord
23 September 2014 в 12:38
Foo
только после того, как завершено возвращенное Task
, что мне не нравится, потому что оно излишне вводит параллелизм.
– svick
23 September 2014 в 13:47