Объявление типа возврата метода Task <int>без асинхронного ключевого слова - PullRequest
0 голосов
/ 16 февраля 2019

В какой ситуации вы бы вернули Task<T> без использования async в сигнатуре метода?

У меня есть такой метод в приведенном ниже коде, но у меня возникают проблемы с пониманием того, что происходит.

Почему мой пример кода ниже не выполняется после любого из операторов await?то есть.почему Console.WriteLine("4)"); и Console.WriteLine("3)"); и return x; никогда не исполняются?

class Program
    {
        static void Main(string[] args)
        {
            TestAsync testAsync = new TestAsync();
            testAsync.Run();

            Console.Read();
        }
    }

    public class TestAsync
    {
        public async void Run()
        {
            Task<int> resultTask = GetInt();
            Console.WriteLine("2)");
            int x = await resultTask;
            Console.WriteLine("4)");
        }
        public async Task<int> GetInt()
        {
            Task<int> GetIntAfterLongWaitTask = GetIntAfterLongWait();
            Console.WriteLine("1)");
            int x = await GetIntAfterLongWaitTask;
            Console.WriteLine("3)");
            return x;
        }

        public Task<int> GetIntAfterLongWait()
        {            
            Task.Run(() =>
            {
                for (int i = 0; i < 500000000; i++)
                {
                    if (i % 10000000 == 0)
                    {
                        Console.WriteLine(i);
                    }
                }
            });

            Console.WriteLine("Returning 23");
            return new Task<int>(() => 23);
        }
    }

/*
Output is:
Returning 23
1)
2)
<list of ints>
*/

Ответы [ 3 ]

0 голосов
/ 16 февраля 2019

Когда вы возвращаете Task из не async метода?

Task<T> обобщенно произносят обещание для будущее значение.Создаете ли вы это обещание из метода async с ключами или из другого источника (например, запущенного потока или обратных вызовов ввода-вывода), это не представляет интереса для вызывающей стороны и представляет собой только стратегию реализации.По этой же причине интерфейсы (или определение абстрактного метода) вообще не имеют ключевого слова async (async / await - это стратегия реализации).

Ваш пример кода

  • Проблема 1 : Ваш метод GetIntAfterLongWait имеет два недостатка.Первый экземпляр Task создается и выгружается в поток, но результат никогда не получается (поэтому никогда не ожидается ... и никогда ничего не задерживается).
  • Issue 2 : Вторая задача (та, которую вы возвращаете в GetIntAfterLongWait) создана (конструктором с методом для выполнения), но не запущена (Task.Start()).Другими более простыми методами являются статические Task.Run или (в данном случае) Task.FromResult.Задача (или обещание) никогда не доставляет результат, поскольку функциональный блок в конструкторе никогда не выполняется.
  • Проблема 3 : Метод Main не ожидает результата возвращенного результата.задание (либо await или Task.Wait(), либо Task.Result.
0 голосов
/ 16 февраля 2019

Проблема в вашем коде в том, что вы на самом деле await никогда не запускали задачу, так как метод GetIntAfterLongWait возвращает новый экземпляр задачи, которая не была запущена.Таким образом, в основном у вас есть тупик, ожидающий чего-то, что вообще не запускается.

Вы можете вернуть Task.FromResult(23), который в основном является уже выполненным заданием, или вы могли бы фактически запустить ваше задание Task.Run<int>(() => 23);

0 голосов
/ 16 февраля 2019

Вероятно, вы создаете новую тему в методе GetIntAfterLongWait().Попробуйте изменить return new Task<int>(() => 23); на return Task.FromResult(23);.

Для получения дополнительной информации о Task.FromResult см. Документацию MSDN (с хорошим примером) на Как: создать предварительно вычисленные задачи

...