Как работать с gui из Async? Ну вот например : есть progressbar и есть button у которого на событии Async onclick лежит следующий код Await Task.Run((){progressbar.value = 77}) и он конечно же "вылетает", так вот, что мне делать?
Asked
Active
Viewed 240 times
3
andreycha
- 25,167
- 4
- 46
- 82
alex-rudenkiy
- 4,012
2 Answers
5
Как вариант можно использовать 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<int> progress = new Progress<int>(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);
});
}
Lightness
- 3,476
-
-
1
-
-
-
@Lightness: Нет, что вы, я без всякой задней мысли. Все три варианта отличные. У вас мой +1. – VladD Jun 09 '16 at 20:00
-
3
Самый простой вариант — если вы уж находитесь в 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.
VladD
- 206,799
Task.Run, а не просто async-обработчик. Покажите весь код. – VladD Jun 09 '16 at 16:54