Страницы

Поиск по вопросам

воскресенье, 2 февраля 2020 г.

Как работать с gui из Async потока? [дубликат]

#c_sharp #многопоточность #асинхронность #async_await


        
             
                
                    
                        
                            На этот вопрос уже даны ответы здесь:
                            
                        
                    
                
                        
                            Работа с контролами из фонового потока
                                
                                    (2 ответа)
                                
                        
                                Закрыт 3 года назад.
            
                    
Как работать с gui из Async? Ну вот например : есть progressbar и есть button у которого
на событии Async onclick лежит следующий код Await Task.Run((){progressbar.value =
77}) и он конечно же "вылетает", так вот, что мне делать?
    


Ответы

Ответ 1



Самый простой вариант — если вы уж находитесь в async-функции, то не вызывайте Task.Run раньше времени. Например, вы можете сделать как-то так: async void OnClick(object sender, RoutedEventArgs e) { button.IsEnabled = false; for (int i = 0; i < 10; i++) { // выгружаем в фоновый поток ту операцию, которая должна быть асинхронной bool isGood = await Task.Run(() => ComputePart(i)); // остаток кода продолжает бежать в UI-потоке if (isGood) progressBar.Value = i; } button.IsEnabled = true; } Ещё три варианта описаны в отличном ответе @Lightness.

Ответ 2



Как вариант можно использовать SynchronizationContext. Пример: private async void ChangeProgressBar() { var uiSync = SynchronizationContext.Current; await Task.Run(() => { uiSync.Send(state => { progressbar.value = 77 }, null); }); } Также можно использовать Progress< T>. Пример: private async void ChangeProgressBar() { IProgress progress = new Progress(value => { progressBar.Value = value; }); await Task.Run(async () => { for (int i = 0; i < 100; i++) { progress.Report(i); await Task.Delay(20); } }); } Еще один вариант это использование Dispatcher. Пример: private async void ChangeProgressBar() { await Task.Run(() => { progressBar.Dispatcher.Invoke(() => progressBar.Value = 77, DispatcherPriority.Background); }); }

Комментариев нет:

Отправить комментарий