Форум программистов, компьютерный форум, киберфорум
C# .NET
Войти
Регистрация
Восстановить пароль
Блоги Сообщество Поиск Заказать работу  
 
Рейтинг 4.83/18: Рейтинг темы: голосов - 18, средняя оценка - 4.83
0 / 0 / 1
Регистрация: 10.01.2014
Сообщений: 18

Проблемы с конструкцией async\await при использовании WPF или Windows Forms

29.03.2014, 23:47. Показов 3471. Ответов 4
Метки нет (Все метки)

Студворк — интернет-сервис помощи студентам
Добрый день!

Написал библиотечку, использующую, в том числе конструкции async-await. Всё работает, при компиляции в виде консольного приложения, выполняется на ура.

Подключил библиотечку к WPF-проекту, пытаюсь использовать (там, собственно, обращение к одному методу)... и наблюдаю зависание. Смотрю: где затык. Оказывается вот где:

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
...
foreach (XElement rootElement in rootElements.Elements())
    PartsParser(rootElement.Name.LocalName, rootElement.Elements());
...
 
private async void PartsParser(string partName, IEnumerable<XElement> partElements)
{
            _inWorkList.Add(partName);
            int count = 0;
            switch (partName)
            {
                ...
                case "Trade":
                    count = await TradeAsync(partElements);
                    break;
                case "WorldOutlooks":
                    count = await WorldAsync(partElements);
                    break;
                case "Buildings":
                    count = await BuildingAsync(partElements);
                    break;
                ...
            }
            Log("Заголовки раздела " + partName + " загружены (" + count + " шт.)";
            _inWorkList.Remove(partName); // используется для синхронизации потоков.
        }
Поясняю:
1. Некий метод обращается к асинхронному методу, который выбирает - что именно асинхронно прочитать в XDocument. Под каждый part этого XDocument имеется свой асинхронный метод.
2. Например, TradeAsync это:

C#
1
2
3
4
5
6
7
8
9
private async Task<int> TradeAsync(IEnumerable<XElement> partElements) 
         return await Task.Run(() =>
            {
                int count = 0;
                foreach (XElement subPartElement in partElements)
                ...
                return count;
            });
        }
3. Затык оказывается в методе PartsParser. Если быть точным, то команды после await не выполняются и до синхронизирующего исключения из List никогда не доходят. Я только начал разбираться с async-await. И вроде как написано, что после завершения потока, команды в методе, который асинхронно вызывал другой метод с await - должны бы выполнятся. И они выполняются, если это не WPF или WinForms.

Вопрос в следующем: почему?
Также происходит и с WinForms. Подключаю библиотеку, запускаю... наблюдаю, что команды после await не исполняются... Подскажите - в чем проблема? Что я упускаю?

Заранее благодарю.
0
cpp_developer
Эксперт
20123 / 5690 / 1417
Регистрация: 09.04.2010
Сообщений: 22,546
Блог
29.03.2014, 23:47
Ответы с готовыми решениями:

Async/await или разница между 2 методами
Добрых времени суток. Есть асинхронный метод: public Task&lt;List&lt;Address&gt;&gt; GetAllByStreet(string street) { return...

Windows Forms или WPF?
Добрый день! У меня есть необходимость написать некую корпоративную CRM систему для нужд компании. Вот думаю, какую технологию...

Используют ли сейчас Windows Forms или все перешли на WPF?
Используют ли сейчас windows forms или все перешли на wpf? Насколько я знаю то винформы очень устарели. Мне интерестно используется эта...

4
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
30.03.2014, 02:10
лишний await:
C#
1
2
3
4
5
6
7
8
9
private Task<int> TradeAsync(IEnumerable<XElement> partElements) 
         return Task.Run(() =>
            {
                int count = 0;
                foreach (XElement subPartElement in partElements)
                ...
                return count;
            });
        }
так код выглядит чище:
C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
private async void PartsParser(string partName, IEnumerable<XElement> partElements)
{
            _inWorkList.Add(partName);
            Func<IEnumerable<XElement>, Task<int>> f = null;
 
            switch (partName)
            {
                ...
                case "Trade":
                    f = TradeAsync;
                    break;
                case "WorldOutlooks":
                    f = WorldAsync;
                    break;
                case "Buildings":
                    f = BuildingAsync;
                    break;
                ...
            }
 
            int count = await f(partElements);            
            Log("Заголовки раздела " + partName + " загружены (" + count + " шт.)";
            _inWorkList.Remove(partName); // используется для синхронизации потоков.
        }
0
0 / 0 / 1
Регистрация: 10.01.2014
Сообщений: 18
30.03.2014, 14:27  [ТС]
Увы, до команд:

C#
1
2
Log("Заголовки раздела " + partName + " загружены (" + count + " шт.)";
_inWorkList.Remove(partName); // используется для синхронизации потоков.
Всё равно не доходит. Чет я нихрена не понимаю.
Т.е. поток не исключается из _inWorkList, соответственно синхронизация потоков вида

C#
1
2
3
while (_inWorkList.Count > 0)
            {
            }
... уходит в бесконечность.

Что интересно: все потоки отрабатывают, т.е. если поставить break point на конце async-метода, результат в виде количества прочтенных заголовков можно наблюдать. Но вот возврата этого значения вызывавшему главному потоку не происходит

Добавлено через 14 минут
И ещё вот что интересно. И что меня особенно смущает. Если поставить break point на int count = await f(partElements) (за совет по большей чистоте кода спасибо отдельное).... то иногда (заметьте, иногда!) выполнение доходит до строки Log("Заголовки раздела " + partName + " загружены (" + count + " шт.)". Причем всегда разных разделов.

И ни сообщений об ошибках, ни каких-то предупреждений... вообще ничего. Я не понимаю.

Добавлено через 1 час 28 минут
Экспериментальным путем выяснилось, что проблема не имеет отношения к тому, где находится код - в DLL или нет. Причем, при отладке DLL, если запустить как Консольное приложение или как Приложение Windows - всё выполняется быстро и легко. Даже если присоединить библиотеку к консольному приложению - тоже всё выполняется легко. А вот WPF или WinForms - проблема.

Добавлено через 48 минут
Эксперименты продолжаются. Вот это, в частности, работает. Почему аналогичное не работает в другой ситуации - не понятно. Отличия, собственно, минимальные: это прямо в коде UI, а исходное - в отдельном классе отдельной DLL.

C#
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
        private void Button_Click_1(object sender, RoutedEventArgs e)
        {
            for (int i = 0; i < 4; i++)
                Parter(i);
        }
 
        private async void Parter(int i)
        {
            string rrr = "ooopps";
            switch (i)
            {
                case 0:
                    rrr = await DoWork0();
                    break;
                case 1:
                    rrr = await DoWork1();
                    break;
                case 2:
                    rrr = await DoWork2();
                    break;
                case 3:
                    rrr = await DoWork3();
                    break;
 
            }
            Debug.Print("Chunk " + rrr);
        }
 
 
        private Task<string> DoWork0()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(2500);
                return "zero";
            });
        }
 
        private Task<string> DoWork1()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(500);
                return "one";
            });
        }
 
        private Task<string> DoWork2()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(5000);
                return "two";
            });
        }
 
        private Task<string> DoWork3()
        {
            return Task.Run(() =>
            {
                Thread.Sleep(500);
                return "three";
            });
        }
0
Каратель
Эксперт С++
6610 / 4029 / 401
Регистрация: 26.03.2010
Сообщений: 9,273
Записей в блоге: 1
30.03.2014, 14:38
выложите что ли проект, чтоб можно было запустить и проверить
0
0 / 0 / 1
Регистрация: 10.01.2014
Сообщений: 18
30.03.2014, 14:41  [ТС]
Чьерт!!! Удалив мою "синхронизацию" потоков в виде

C#
1
while (_inWorkList.Count > 0) { }
Всё заработало! Я имею ввиду исходный вариант. Следовательно, правильно ли я понимаю - вопрос в неправильной синхронизации, которая осуществляется из главного потока. Т.е. главный поток что-то там блокирует и не позволяет остальным потокам...))

Т.е. у меня вызов метода в библиотеке происходил из основного потока UI (допустим, нажатием клавиши), затем он блокировался синхронизацией... и в ней почему-то оставался, не позволяя другим потокам закончить работу. Выход я вижу в следующем - запустить вообще всё выполнение в библиотеке в отдельном потоке... Как-то так.

Подскажите, кто понимает в чем моя ошибка. Заранее благодарю.

Цитата Сообщение от Jupiter Посмотреть сообщение
выложите что ли проект, чтоб можно было запустить и проверить
Увы, не имею права. За нами следят)))
0
Надоела реклама? Зарегистрируйтесь и она исчезнет полностью.
raxper
Эксперт
30234 / 6612 / 1498
Регистрация: 28.12.2010
Сообщений: 21,154
Блог
30.03.2014, 14:41
Помогаю со студенческими работами здесь

Async, await
Объясните работу async, await. Облазил весь интернет, но ничего толкового не нашел. Заранее спасибо))

Использование async/await
пытался написать такой тестовый код: нифига не работает, я видимо что-то неправильно делаю. Что именно, не знаю :) using System; using...

Понимание потоков и async await
Всем привет, хочу задать пару вопросов опытным программистам: 1)Что такое потоки ? как они реализованы в .net и как реально выполняются...

Async/await различия методов
В чем разница между AsyncWork1/2/3 private async void btnStart_Click_1(object sender, EventArgs e) { ...

Пауза через async/await
Написал процедуру Пауза на C# с помощью async/await, но почему-то не работает. Вот код: private void button11_Click(object sender,...


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

Или воспользуйтесь поиском по форуму:
5
Ответ Создать тему
Новые блоги и статьи
PhpStorm 2025.3: WSL Terminal всегда стартует в ~
and_y87 14.12.2025
PhpStorm 2025. 3: WSL Terminal всегда стартует в ~ (home), игнорируя директорию проекта Симптом: После обновления до PhpStorm 2025. 3 встроенный терминал WSL открывается в домашней директории. . .
Access
VikBal 11.12.2025
Помогите пожалуйста !! Как объединить 2 одинаковые БД Access с разными данными.
Новый ноутбук
volvo 07.12.2025
Всем привет. По скидке в "черную пятницу" взял себе новый ноутбук Lenovo ThinkBook 16 G7 на Амазоне: Ryzen 5 7533HS 64 Gb DDR5 1Tb NVMe 16" Full HD Display Win11 Pro
Музыка, написанная Искусственным Интеллектом
volvo 04.12.2025
Всем привет. Некоторое время назад меня заинтересовало, что уже умеет ИИ в плане написания музыки для песен, и, собственно, исполнения этих самых песен. Стихов у нас много, уже вышли 4 книги, еще 3. . .
От async/await к виртуальным потокам в Python
IndentationError 23.11.2025
Армин Ронахер поставил под сомнение async/ await. Создатель Flask заявляет: цветные функции - провал, виртуальные потоки - решение. Не threading-динозавры, а новое поколение лёгких потоков. Откат?. . .
Поиск "дружественных имён" СОМ портов
Argus19 22.11.2025
Поиск "дружественных имён" СОМ портов На странице: https:/ / norseev. ru/ 2018/ 01/ 04/ comportlist_windows/ нашёл схожую тему. Там приведён код на С++, который показывает только имена СОМ портов, типа,. . .
Сколько Государство потратило денег на меня, обеспечивая инсулином.
Programma_Boinc 20.11.2025
Сколько Государство потратило денег на меня, обеспечивая инсулином. Вот решила сделать интересный приблизительный подсчет, сколько государство потратило на меня денег на покупку инсулинов. . . .
Ломающие изменения в C#.NStar Alpha
Etyuhibosecyu 20.11.2025
Уже можно не только тестировать, но и пользоваться C#. NStar - писать оконные приложения, содержащие надписи, кнопки, текстовые поля и даже изображения, например, моя игра "Три в ряд" написана на этом. . .
Мысли в слух
kumehtar 18.11.2025
Кстати, совсем недавно имел разговор на тему медитаций с людьми. И обнаружил, что они вообще не понимают что такое медитация и зачем она нужна. Самые базовые вещи. Для них это - когда просто люди. . .
Создание Single Page Application на фреймах
krapotkin 16.11.2025
Статья исключительно для начинающих. Подходы оригинальностью не блещут. В век Веб все очень привыкли к дизайну Single-Page-Application . Быстренько разберем подход "на фреймах". Мы делаем одну. . .
КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2025, CyberForum.ru