Я пишу базовый код Firebase в приложении Xamarin для iOS и сталкиваюсь с классической тупиковой ситуацией с ошибкой TaskCompletionSource
.
public Task<string> GetUsers()
{
var tcs = new TaskCompletionSource<string>();
_instance.GetChild("users").ObserveSingleEvent(DataEventType.Value,
x => { tcs.SetResult(x); });
return tcs.Task;
}
Когда я блокирую этот код так:
var users = GetUsers().Result;
Приложение блокируется.
Если я правильно понимаю, обратный вызов пытается запуститься в том же контексте, что и .Result
.
Чего я не понимаю, так это того, что если я изменю свой код, чтобы ожидать вызова GetUsers()
в Task
, например так:
var result = Task.Run(
async () => await AppContext.Database.GetUsers().ConfigureAwait(false)
).Result;
Это все еще тупики.
Что здесь происходит во втором случае? Не должен ли тот факт, что код выполняется в другом потоке из-за Task.Run
, означать, что внешний .Result
не блокирует вызов обратного вызова?
ИЗМЕНИТЬ:
В продолжение комментария Нкоси я спрашиваю об этом, потому что мне любопытно, почему код блокируется. Если я жду звонка
var users = await GetUsers().ConfigureAwait(false);
тогда тупик уходит. Я просто хотел бы понять, почему он блокируется при заключении в Task
, потому что, исходя из моего (явно неправильного) понимания Task.Run
, этого не должно быть.
var users = await Getusers().ConfigureAwait(false)
, код запустится без взаимоблокировки. Мне просто любопытно, почему версияTask.Run
не работает, потому что, насколько я понимаю, должна. - person Levi Botelho   schedule 10.06.2017