Будет ли вызывающий поток заблокирован, если Task.Result вызывается в функции возврата Task - PullRequest
0 голосов
/ 12 января 2019

Я стараюсь не создавать избыточные Task объекты в моем коде, и я пишу Task возвращающие функции вместо async Task функций, где это возможно.

Когда необходимо сохранить значение, возвращаемое функцией async, я вынужден заставить функцию вернуть async Task и вызвать функцию с помощью await.

Пример:

async Task SomeWorkAsync()
{
   someGlobalVariable = await AnotherWorkAsync();
}

То, что я написал вместо:

Task SomeWorkAsync()
{
   var task = AnotherWorkAsync();
   someGlobalVariable = task.Result;
   return task;
}

Но я боюсь, что он заблокирует вызывающий поток, как это делает синхронный код.

await SomeWorkAsync(); //main thread block

Есть ли другой способ переписать код в примере без переноса всей функции с новым Task, как это делает ключевое слово async?

Ответы [ 3 ]

0 голосов
/ 12 января 2019

Я пытаюсь не создавать избыточные объекты Task в своем коде и пишу функции, возвращающие Task, вместо асинхронных функций Task, где это возможно.

Это не обычный и не предполагаемый способ работы с TPL.

Это неправильно:

Task SomeWorkAsync()
{
   var task = AnotherWorkAsync();
   someGlobalVariable = task.Result;
   return task;
}

Вы должны использовать

async Task<T> SomeWorkAsync()
{
   someGlobalVariable = await AnotherWorkAsync();
   return someGlobalVariable;
}

Только при строгих обстоятельствах вы должны использовать .Result, чтобы получить результат Task.

0 голосов
/ 20 января 2019

Чтобы ответить на ваш вопрос:

  1. Да, вызов .Result заблокирует ваш поток.
  2. См. Мой комментарий о том, почему я считаю, что лучше использовать await, а не возвращать задачу: https://stackoverflow.com/a/54211382/918058
0 голосов
/ 12 января 2019

Если вы хотите сохранить себе конечный автомат, просто позвоните

public Task SomeWorkAsync()
{
   ...
   return AnotherWorkAsync();
}

Не вызывайте Result, просто верните задачу без ключевого слова async в определении метода

Короче говоря, вы просто возвращаете задание, которое можно ожидать выше

Обновление

Да, это помогает, если AnotherWorkAsync - асинхронная задача, но в моем дело это асинхронно Task<T>

public Task<MyAwesomeType> SomeWorkAsync()
{
   ...
   return AnotherWorkAsync();
}

Обновление 2

Это все еще не то, что я имею в виду. Класс, который будет вызывать SomeWorkAsync ничего не знает о закрытой переменной someGlobalVariable. это необходимо получить значение и установить эту переменную внутри

public async Task SomeWorkAsync()
{
   someGlobalVariable = await AnotherWorkAsync();
}

Если вам нужен результат асинхронного метода, вам придется await.

Старайтесь не смешивать синхронный код и шаблон async await, который вы делаете с Result, вы можете вызвать взаимные блокировки ... просто позвольте async распространяться

...