|
Вызов асинхронного метода из синхронного
|
|||
---|---|---|---|
#18+
Добрый день. Такая ситуация: 1. Есть асинхронный метод, который, помимо await-вызовов, взаимодействует с UI (WPF, если это существенно). 2. Этот асинхронный метод, в зависимости от внешних обстоятельств, может выбрасывать ошибки, и такие ситуации нужно обрабатывать в т.ч. на уровне UI. 3. Модифицировать этот асинхронный метод (чтобы встроить туда обработку ошибок) нельзя (мопед не мой). 3. Этот асинхронный метод нужно вызвать из синхронного. При этом не нужно дожидаться окончания отработки этого метода, вполне устроит просто запустить его - но вот как быть с обработкой ошибок? Попробовал вот так (схематично): Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
(Progress привязан в качестве ItemsSource к листбоксу - просто для имитации нескольких последовательных взаимодействий с UI). Пытаюсь запустить: Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12. 13. 14. 15. 16.
Task.Factory.StartNew использовался для запуска потому, что он позволяет задать контекст синхронизации (а в Task.Run я такой возможности не нашёл). Требуемый метод запускается вполне нормально, первые 3 строки добавляются в листбокс, но PrepareError не вызывается - как выяснилось, по причине указания TaskContinuationOptions.OnlyOnFaulted. Если параметр с TaskContinuationOptions вообще убрать, то по консольному выводу видно, что PrepareError вызывается ещё до окончания отработки AsyncTest (и до возникновения ошибки). Как быть в данном случае? ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2021, 15:03 |
|
Вызов асинхронного метода из синхронного
|
|||
---|---|---|---|
#18+
WinterGraveyard При этом не нужно дожидаться окончания отработки этого метода ... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2021, 15:24 |
|
Вызов асинхронного метода из синхронного
|
|||
---|---|---|---|
#18+
А что мешает сделать свой метод асинхронным как "async void": Код: c# 1. 2. 3. 4. 5. 6. 7. 8. 9. 10. 11. 12.
... |
|||
:
Нравится:
Не нравится:
|
|||
19.04.2021, 17:06 |
|
Вызов асинхронного метода из синхронного
|
|||
---|---|---|---|
#18+
fkthat, Спасибо, и действительно - что-то я так завяз в разбирательстве с ContinueWith, что такой простой вариант упустил. Однако хотелось бы всё же разобраться - просто для лучшего понимания - почему в моём вышеприведённом случае этот continuation task выполняется без ожидания выполнения асинхронного делегата? Та же внутри имеется await - получается, что он ничего не ждёт, а просто создаёт Task, запускает его, и возвращает выполнение? Несмотря на await? ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2021, 06:54 |
|
Вызов асинхронного метода из синхронного
|
|||
---|---|---|---|
#18+
WinterGraveyard Та же внутри имеется await - получается, что он ничего не ждёт, а просто создаёт Task, запускает его, и возвращает выполнение? Несмотря на await? Да, именно так. Task.Run с асинхронным делегатом и await ждёт, Task.Start - нет: https://stackoverflow.com/a/31584851 Using an async delegate inside Task.Run means that you actually run a Task<Task>. This is hidden from you by the fact that Task.Run is async aware and unwraps the inner task for you, something that Task.Factory.StartNew didn't do и этот факт виден по требуемой сигнатуре Action для ContinueWith - в случае для Task.Run это Action<Task> (если не передавать состояние) - то есть действительно Task.Run unwraps the inner task for you . А для Task.Start это Action<Task<Task>>, и никакого unwrap нет. В данном случае, поскольку Task.Run использовать не получается, то можно сделать так: Код: 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.
Я не думаю, что очень ожидание выполнения микротаска на старт другого таска будет критичным для чего-либо. Но лучше, конечно, предложенный выше способ (с заворачиванием вызова метода в свой async-метод с обработкой ошибок). Он как минимум нагляднее. ... |
|||
:
Нравится:
Не нравится:
|
|||
20.04.2021, 11:32 |
|
|
start [/forum/topic.php?fid=20&tid=1398318]: |
0ms |
get settings: |
9ms |
get forum list: |
14ms |
check forum access: |
4ms |
check topic access: |
4ms |
track hit: |
38ms |
get topic data: |
11ms |
get forum data: |
3ms |
get page messages: |
41ms |
get tp. blocked users: |
1ms |
others: | 274ms |
total: | 399ms |
0 / 0 |