Как выполнить задачу на фоне wpf, когда вы можете предоставить отчет и разрешить аннулирование?
Я хочу выполнить долговременную задачу после нажатия кнопки wpf. Вот что я сделал.
private void Start(object sender, RoutedEventArgs e) { for (int i = 0; i < 10; i++) { Thread.Sleep(2000); // simulate task } }
Проблема в том, что wpf gui не отвечает. Я также хотел бы разрешить отмену и отчет о прогрессе каждые 1 секунду. Я расширяю код, как показано ниже.
DispatcherTimer dispatcherTimer = new DispatcherTimer(); // get progress every second private int progress = 0; // for progress reporting private bool isCancelled = false; // cancellation private void Start(object sender, RoutedEventArgs e) { InitializeTimer(); // initiallize interval timer Start(10); // execute task } private void InitializeTimer() { dispatcherTimer.Tick += dispatcherTimer_Tick; dispatcherTimer.Interval = new TimeSpan(0,0,1); dispatcherTimer.Start(); } private void dispatcherTimer_Tick(object sender, EventArgs e) { Logger.Info("Current loop progress " + progress); // report progress } private void Cancel(object sender, RoutedEventArgs e) // cancel button { isCancelled = true; } private int Start(int limit) { isCancelled = true; progress = 0; for (int i = 0; i < limit; i++) { Thread.Sleep(2000); // simulate task progress = i; // for progress report if (isCancelled) // cancellation { break; } } return limit; }
Моя целевая платформа – .NET 4.5. Каков рекомендуемый способ сделать это?
- Привязать к значению, определенному в настройках
- Откройте диалоговое окно файла и выберите файл с помощью элементов управления WPF и C #
- Как создать пользовательский хром в wpf?
- Как приложение Metro в Windows 8 взаимодействует с настольным настольным окном на одном компьютере?
- Загрузите ResourceDictionary из сборки
Благодарю.
- отображать Песочные часы, когда приложение занято
- Установить цвет фона текстового поля WPF в коде C #
- WPF TextBox для ввода десятичных значений
- Как связать массив байтов с изображением в WPF с преобразователем значений?
- Модель Mvvm ViewModel
- WPF: отобразить значение bool как «Да» / «Нет»
- Как поддерживать привязку ListBox SelectedItems к MVVM в навигационном приложении
- MVVM Dynamic Menu UI от привязки с ViewModel
Я думал, что ответил на ваш вопрос. Если вам нужно больше кода примера о том, как это сделать, используя параллельную библиотеку задач, с CancellationTokenSource
и IProgress
, вот оно:
Action _cancelWork; private async void StartButton_Click(object sender, RoutedEventArgs e) { this.StartButton.IsEnabled = false; this.StopButton.IsEnabled = true; try { var cancellationTokenSource = new CancellationTokenSource(); this._cancelWork = () => { this.StopButton.IsEnabled = false; cancellationTokenSource.Cancel(); }; var limit = 10; var progressReport = new Progress((i) => this.TextBox.Text = (100 * i / (limit-1)).ToString() + "%"); var token = cancellationTokenSource.Token; await Task.Run(() => DoWork(limit, token, progressReport), token); } catch (Exception ex) { MessageBox.Show(ex.Message); } this.StartButton.IsEnabled = true; this.StopButton.IsEnabled = false; this._cancelWork = null; } private void StopButton_Click(object sender, RoutedEventArgs e) { this._cancelWork?.Invoke(); } private int DoWork( int limit, CancellationToken token, IProgress progressReport) { var progress = 0; for (int i = 0; i < limit; i++) { progressReport.Report(progress++); Thread.Sleep(2000); // simulate a work item token.ThrowIfCancellationRequested(); } return limit; }
BackgroundWorker
– это то, что вы ищете вместо DispatcherTimer.
Он обеспечивает поддержку отмены (через WorkerSupportsCancellation ) и сообщает о прогрессе в streamе пользовательского интерфейса (через WorkerReportsProgress ).
См. Превосходную подробную статью здесь – Как использовать BackgroundWorker .