Анализатор обнаружил более одного использования одного и того же '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); // <= }
Решения проблемы в таких случаях полностью аналогичны решениям, описанным ранее.