Анализатор обнаружил более одного использования одного и того же 'UnityEngine.Awaitable' объекта с оператором 'await'. В целях оптимизации 'Awaitable' объекты хранятся в пуле-объектов. При использовании 'await' объект 'Awaitable' возвращается в пул. После этого при повторном применении 'await' к этой же ссылке объекта будет выброшено исключение, в некоторых случаях также возможна взаимная блокировка.
Рассмотрим синтетический пример:
async Awaitable<bool> AwaitableFoo() { .... }
async Awaitable ExampleFoo()
{
Awaitable<bool> awaitable = AwaitableFoo();
if (await awaitable)
{
var result = await awaitable;
....
}
}
В этом коде будет выброшено исключение (или возникнет взаимная блокировка) при инициализации переменной 'result' значением, полученным при использовании 'await' к 'awaitable'. Это произойдёт из-за того, что ранее 'await' уже применялся к 'awaitable' в условии условной конструкции.
Чтобы обезопасить этот код, следует избегать записи 'Awaitable' в переменную. Вместо этого можно переиспользовать значение, полученное после вызова 'AwaitableFoo()' c использованием 'await':
async Awaitable<bool> AwaitableFoo() { .... }
async Awaitable ExampleFoo()
{
bool value = await AwaitableFoo();
if (value)
{
var result = value;
....
}
}
Или повторно выполнять вызов с 'await' непосредственно метода 'AwaitableFoo' там, где это требуется:
async Awaitable<bool> AwaitableFoo() { .... }
async Awaitable ExampleFoo()
{
if (await AwaitableFoo())
{
var result = await AwaitableFoo();
....
}
}
Такое решение также является корректным, ведь при каждом вызове 'AwaitableFoo()' будет возвращён новый объект 'Awaitable'.
Стоит отметить, что возможны и менее очевидные случаи возникновения проблемы. Например, когда повторное применение 'await' к значению 'Awaitable' происходит внутри другого метода, которому это значение было передано в качестве аргумента:
async Awaitable<bool> AwaitableFoo() { .... }
async Awaitable<Result> GetResult(Awaitable<bool> awaitable)
{
if (await awaitable){ .... } // <=
else { .... }
}
async Awaitable ExampleFoo()
{
Awaitable<bool> awaitable = AwaitableFoo();
if (await awaitable) // <=
{
....
}
var result = await GetResult(awaitable); // <=
}
Решения проблемы в таких случаях полностью аналогичны решениям, описанным ранее.