#c# #wpf
Вопрос:
Я пытаюсь реализовать кнопку; которая меняет свою метку на «Вход…», сохраняет эту метку до завершения события, а затем снова меняет свою метку на старую. Но в этом интервале он не должен зависать (в основном поток пользовательского интерфейса будет продолжать выполняться). Какой алгоритм можно выполнить здесь? Я только что использовал этот код, но он не работает ожидаемо:
Task.Factory.StartNew(() =>
{
string old_label = sign_in_button.label.Content;
Application.Current.Dispatcher.BeginInvoke(DispatcherPriority.Input,
new Action(() => {
sign_in_button.label.Content = "Signing in...";
}));
// Event gets executed here...
sign_in_button.label.Content = old_label;
});
Комментарии:
1. Очевидно, что при доступе к вашему из фонового потока у вас есть две недопустимые операции между потоками
sign_in_button
. Вы должны всегда обращаться к нему с помощью диспетчера, как вы делали это один раз. Но что именно работает не так, как ожидалось?2. Это в основном не меняет содержание метки, я также поставил ящик сообщений после определения old_label, и он не был выполнен.
3. Это связано с тем, что первая строка кода обращается к вашей кнопке из фонового потока, который создает исключение. Вы не ждете своей задачи, поэтому исключение «потеряно». Попробуйте, как предлагает @Lingam
Ответ №1:
Вы можете использовать асинхронное ожидание. Пример кода ниже. Вы также можете передать диспетчер главного окна в свой новый поток, если вы планируете обновить или извлечь оттуда некоторые данные пользовательского интерфейса.
private async void Button_Click(object sender, RoutedEventArgs e)
{
var _dispatcher = App.Current.MainWindow.Dispatcher;
string old_label = sign_in_button.Content as string;
sign_in_button.Content = "Signing in...";
// Event gets executed here...
await Task.Run(() => signIn(_dispatcher));
sign_in_button.Content = old_label;
}
private void signIn(Dispatcher _dispatcher)
{
//THREAD DELAY TEST
Thread.Sleep(3500);
_dispatcher.BeginInvoke(() => { sign_in_button.Content = "Changed from another thread"; },DispatcherPriority.Send);
Thread.Sleep(3500);
}
Комментарии:
1. Верно. Я думаю, что раньше я неправильно понимал, что такое диспетчер. Теперь я понял, как именно он используется. Спасибо.