4 / 5 / 1
Регистрация: 25.05.2012
Сообщений: 261
Записей в блоге: 1
1

Почему Task никогда не завершается?

07.04.2019, 11:59. Показов 2111. Ответов 6

Добрый день!

Пробую свои силы в async/await.
Подскажите, почему в данном коде никогда не происходит события task.IsCompleted? На выходе просто вижу изменение таймера и сообщение "Wait for .... milliseconds".

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
 public void StartAsyncMethod(int value)
        {
            int timer = 0;
            MyAsyncClass myAsyncClass = new MyAsyncClass();
            Task task = myAsyncClass.AsyncMethod(value*1000);
            while (!task.IsCompleted)
            {
               timer++;
               Thread.Sleep(1000);
               ShowTimer(timer);
            }
             Console.WriteLine("StartAsyncMethod Finished!");
        }
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public class MyAsyncClass
    {
        public async Task AsyncMethod(int _i)
        {
            Console.WriteLine($"Wait for {_i} milliseconds");
            await Task.Run(() => Sleep(_i));
            Console.WriteLine($"Finish...");
        }
 
        private void Sleep(int v)
        {
            Thread.Sleep(v);
        }
    }
PS: если удалить цикл While(), то все работает корректно.
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
07.04.2019, 11:59
Ответы с готовыми решениями:

Асинхронный метод долго (никогда?) не завершается
Добрый день. Вызываю асинхронный метод вот так: StockOrderInfo info; ...

Морской бой: Проверка на победителя никогда не завершается
Здравствуйте дорогие форумчане. Есть у меня некий код морского боя, не полный. Проблема у меня...

Почему у конструкторов никогда не пишут тип возвращаемого значения?
Почему у конструкторов никогда не пишут тип возвращаемого значения? Потому что он совпадает с...

Почему в РСФСР-СССР никогда не было скоростного транспортного транзита – трансферта?
Почему в РСФСР-СССР никогда не было скоростного транспортного транзита – трансферта: ни...

6
Эксперт .NET
16746 / 12497 / 3285
Регистрация: 17.09.2011
Сообщений: 20,729
07.04.2019, 15:23 2
skitale, какое значение передаваемого value в метод StartAsyncMethod?
0
4 / 5 / 1
Регистрация: 25.05.2012
Сообщений: 261
Записей в блоге: 1
08.04.2019, 00:48  [ТС] 3
Цитата Сообщение от kolorotur Посмотреть сообщение
skitale, какое значение передаваемого value в метод StartAsyncMethod?
натуральное число - 1, 2 и т.д. - ввожу сам

Может дело в вызове Thread.Sleep(1000) на 9-й строке - не вызывает ли он дедлок?

Добавлено через 45 минут
Цитата Сообщение от skitale Посмотреть сообщение
Может дело в вызове Thread.Sleep(1000) на 9-й строке - не вызывает ли он дедлок?
Нет, дело не в Thread.Sleep(1000) - заменил на for (int i = 0; i < 1000000; i++){} и ситуация не изменилась.
0
Эксперт .NET
16746 / 12497 / 3285
Регистрация: 17.09.2011
Сообщений: 20,729
08.04.2019, 00:50 4
skitale, а что метод ShowTimer делает?

Цитата Сообщение от skitale Посмотреть сообщение
Может дело в вызове Thread.Sleep(1000) на 9-й строке - не вызывает ли он дедлок?
Вряд ли.
0
4 / 5 / 1
Регистрация: 25.05.2012
Сообщений: 261
Записей в блоге: 1
08.04.2019, 01:26  [ТС] 5
Создал отдельное консольное приложение (изначально код писался для AspNet-приложения), вставил приведенный выше код и вот результаты:

С циклом while(!task.IsCompleted) :

Почему Task никогда не завершается?


Без цикла while :

Почему Task никогда не завершается?


Ничего не понимаю.... В консольном приложении код работает корректно, а в AspNet - получается, нет... Почему?
0
4 / 5 / 1
Регистрация: 25.05.2012
Сообщений: 261
Записей в блоге: 1
15.04.2019, 11:05  [ТС] 6
Лучший ответ Сообщение было отмечено КОП как решение

Решение

Цитата Сообщение от skitale Посмотреть сообщение
В консольном приложении код работает корректно, а в AspNet - получается, нет... Почему?
Может быть кому-то будет полезно:

При запуске в ASPNet программа уходила в deadlock из-за того, что в вызывающем методе крутился цикл, ожидавший завершения Task'а в AsyncMethod:
C#
1
2
3
4
5
6
while (!task.IsCompleted)
 {
timer++;
Thread.Sleep(1000);
ShowTimer(timer);
 }
... но данный таск для завершения по-умолчанию пытался выплнить код после await в том же потоке (это настройка по-умолчанию для асинхронного метода - он всегда будет пытаться выполнить код после await в том же контексте, в котором начал выполнеие async-метода). Плюс к тому текущий контекст - однопоточный - это особенность контекстов для ASPNet, WPF, WInForms - везде где есть UI. Получалось, что данный поток был занят ожиданием завершения таска, которому он же был нужен для завершения - классический дедлок.

В консольном приложении этой проблемы не возникло потому что оно при запуске не создает контекста синхронизации, а в таком случае async-метод автоматически создаст свой контекст и без проблем выполнит в нем код после await.

Одно из решений проблемы:
Разрешить компилятору выполнять код после async в любом другом потоке - добавить настройку ConfigureAwait(false):

C#
1
2
3
4
5
6
         public async Task AsyncMethod(int _i)
        {
            WriteOnPage.WriteLine($"Wait for {_i} milliseconds"); //метод WriteOnPage выводит на страницу браузера сообщение
            await Task.Run(() => Sleep(_i)).ConfigureAwait(false);
            WriteOnPage.WriteLine($"Finish...");
        }
Замечание:
Мне сделали замечание, что использовать в условии task.IsCompleted не есть хорошо.
Также рекомендуется использовать вместо Thread.Sleep() метод Task.Delay();

Полезные ссылки по теме:

Мой вопрос с подробным ответом на StackOwerflow.

Андрей Часовских — Async/await: собираем грабли
Видео курс C# Professional. Урок 15. Async Await

На русском стековерфлоу можно посикать по запросу "Почему async/await блокирует UI? [дубликат]"

Хорошая статья про контексты синхронизации на русском. Она же на английском.

Основная книга по асинхронному программированию от Стивена Клири (есть только на английском): "Concurrency in C# Cookbook"

Неплохое объяснение на хабре разницы между многопоточностью и асинхронностью (перевод ужасен, но все же):на русском на английском
0
4 / 5 / 1
Регистрация: 25.05.2012
Сообщений: 261
Записей в блоге: 1
15.04.2019, 17:26  [ТС] 7
Пардон, ошибочное сообщение
Миниатюры
Почему Task никогда не завершается?  
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
15.04.2019, 17:26
Помогаю со студенческими работами здесь

Почему в физике так много разговоров об ускорении, и почти никогда не говорится о замедлении
Почему в физике так много разговоров об ускорении, и почти никогда не говорится о замедлении? ...

Почему приложение не завершается?
Ребята, подскажите.. Есть проект. В нём две формы(скажем frmFirst и frmSecond). Одна из другой...

Почему программа некорректно завершается?
Задачей было написать резидентную программу для DOS, которая проигрывает ноты из массива (1сек на...

Прерывание SIGINT. Почему не завершается программа?
Здравствуйте. Решал такую задачу: 12. Написать программу, предоставляющую информацию обо всех...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
7
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2023, CyberForum.ru