19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|||||||||||
1 | |||||||||||
Как правильно работать с асинхронными методами?25.06.2018, 10:54. Показов 2927. Ответов 16
Метки нет (Все метки)
Добрый день.
Разъясните, мне, пожалуйста, как правильно использовать асинхронные методы, если в программе есть и обычный код? Например, делаю вот так:
Подскажите, пожалуйста, что я делаю не так?
0
|
25.06.2018, 10:54 | |
Ответы с готовыми решениями:
16
Как сделать эти методы асинхронными? Как правильно работать с БД Как правильно работать с АДО ? Как правильно работать с сетками? |
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 11:22 | 2 |
Сообщение было отмечено kolorotur как решение
Решение
Совершаете одну из самых распространенных ошибок при работе с асинхронным кодом: мешаете вместе асинхронное (await) и синхронное (Result) ожидания, что зачастую приводит к зависанию приложения наглухо.
Чтобы этого избежать, в идеале сделайте метод, в котором вызывается PostNewOrder тоже асинхронным и замените обращение к свойству Result на await .Если это по какой-то причине невозможно (например, вызов происходит в аксессоре или в реализации интерфейса), то запускайте вызов PostNewOrder в одном из потоков пула через Task.Run и там уже блокируйте поток вызовом Result.Так же в асинхронных методах, в которых контекст выполнения не имеет значения, имеет смысл в асинхронных вызовах добавлять ConfigureAwait(false) — это немного улучшит производительность и может уменьшить шанс зависания, но последнее, конечно, не гарантируется.
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|||||||||||
25.06.2018, 12:12 [ТС] | 3 | ||||||||||
Вот как раз мой случай.
У меня есть некий алгоритм, который тестирует другой алгоритм на заранее загруженных данных (так называемый бэктестинг). А далее необходимо сделать, чтобы он делал то же самое, но на реальных данных, поступающих в режиме реального времени, но несколько другим способов (сначала был эмулятор, а затем некий реальный объект, который совершает некие действия, в данном случае это торговля на бирже). Чтобы не переписывать всю систему, я как раз и реализовал все это через интерфейс, а вот сейчас выяснилось, что библиотека, работающая с реальной биржей, работает через асинхронные методы. Как тут лучше всего поступить? В соответствующем методе вызывать асинхронный метод бес параметров и каким-то волшебным образом ждать пока он отработает и вернет значения, но ждать не более аймаута, или все таки лучше перелопатить интерфейс и соответственно, сам эмулятор под асинхронные методы. Как я заметил, вот такое вот дело:
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|||||||||||
25.06.2018, 13:06 | 4 | ||||||||||
Если имеется возможность, я бы изменил сигнатуры своих интерфейсов на асинхронные — наиболее приемлемый и наименее костыльный вариант.
Например, было так:
Так лучше не делать, если это не обработчик события. Да и с тем лучше быть осторожным. С async void можно тех еще веселостей набраться.
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|
25.06.2018, 13:11 [ТС] | 5 |
А если потом придется конектиться другой бирже, у которой библиотеки НЕ асинхронные?
А сам эмулятор, его тоже получается надо асинхронным делать, асинхронным? Тут вот еще мысля возникла, может создать какого-нибудь "демона" (поток о есть) который будет обслуживать торговлю основного алгоритма, принимать от него заявки и посылать их асинхронно на биржу?
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 13:15 | 6 |
Намного проще обернуть синхронный метод в асинхронный через Task.Run, чем наоборот.
1
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|
25.06.2018, 13:27 [ТС] | 7 |
Интересно, а если сделать асинхронный метод, но в нем не делать await - ов, он будет работать как синхронный?
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 13:29 | 8 |
Да, вам даже компилятор подчеркнет этот метод и выдаст предупреждение.
В общем-то, и асинхронный метод с await может отработать синхронно если выполнение не требует блокирования потока.
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
||||||
25.06.2018, 14:06 [ТС] | 9 | |||||
И еще какая-то странность.
я сделал так:
Я чего-то видать не понял в асинхронных методах.... Добавлено через 14 минут Или асинхронные методы только в потоке работают?
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 14:16 | 10 |
Потому что асинхронный код у вас начинается после вывода окна сообщения.
Все до этого происходит синхронно. Любой код работает в потоке. Вопрос — в каком
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
||||||
25.06.2018, 14:18 [ТС] | 11 | |||||
Сделал так:
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 14:20 | 12 |
По той же причине: вывод сообщения у вас происходит до выполнения асинхронного кода.
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|
25.06.2018, 14:25 [ТС] | 13 |
Но ведь proba1 вызывается через await, а сообщение вызывается в нем, в методе proba1
Все равно, как то недопонимаю немного, почему так так...
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
|
25.06.2018, 14:39 | 14 |
Наличие await и async в коде не делают метод асинхронным. Асинхронным его делает асинхронная реализация самого метода
async и await используются для управлениея уже имеющейся асинхронностью. Перед тем, как выполняется асинхронное ожидание (await), сначала выполняется метод proba, который возвращает Task. await применяется к возвращаемому Task, а не к самому методу. Само слово await разворачивается компилятором в код, который проверяет статус полученного таска: если работа уже завершена, то извлекается результат (если он есть) и метод продолжает работу дальше. Если же задача находится в процессе, то остаток метода, который идет после await выносится в отдельный метод и подписывается как продолжение полученной задачи, после чего текущий метод завершает работу, возвращая задачу, подписанную на продолжение. Ну или ничего не возвращает, если это async void .Зная это, довольно несложно проследить что происходит в вашем коде: 1. button1_Click: В список добавляется "До". 2. button1_Click: Вызывается метод proba 3. proba: Производится инкремент i 4. proba: Вызывается метод proba1 5. proba1: Показывается сообщение 6. proba1: Вызывается метод Task.Run, который возвращает Task 7. proba1: делается проверка: завершен ли полученный Task. 8. proba1: Если да, то из него извлекается результат и метод proba1 возвращает завершенную задачу с этим результатом. 9. proba1: Если нет, то шаг 8 выносится в отдельный метод, который подписывается на продолжение задачи Task и возвращается задача, представляющая эту "цепочку". 10. proba: Проверяется Task, который вернул метод proba1. 11. proba: Если полученный Task уже завершен (если отработал шаг 8), то метод завершает работу. 12. proba: Если полученный Task еще не завершен (если отработал шаг 9), то метод подписывает остальные инструкции на продолжение этой задачи и завершает работу. В вашем случае продолжения нет, потому метод просто завершает работу. 13. button1_Click: В список добавляется "После". Как видите, у вас сообщение выводится еще до того, как начинает выполняться асинхронный код.
0
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|||||||||||
25.06.2018, 16:07 [ТС] | 15 | ||||||||||
Думал понял... но
Делаю вот так:
0
|
17688 / 12873 / 3366
Регистрация: 17.09.2011
Сообщений: 21,138
|
||||||
25.06.2018, 16:10 | 16 | |||||
Сообщение было отмечено megabax как решение
Решение
megabax, все то же самое: единственный участок с асинхронным кодом у вас — это вызов Task.Run, который отрабатывает очень быстро, т.к. ничего не делает.
Весь остальной код выполняется синхронно. Попробуйте так и сравните:
1
|
19 / 19 / 14
Регистрация: 06.08.2009
Сообщений: 533
|
|
26.06.2018, 08:04 [ТС] | 17 |
kolorotur, Спасибо большущее. Теперь что-то получилось.
0
|
26.06.2018, 08:04 | |
26.06.2018, 08:04 | |
Помогаю со студенческими работами здесь
17
Как правильно работать с Recordset Как правильно работать с NRF24L01? Как правильно работать с данными Как правильно работать с setlocale Искать еще темы с ответами Или воспользуйтесь поиском по форуму: |