如何在wpf背景中执行任务,同时能够提供报告并允许取消?

我想在点击一个wpfbutton后执行一个长时间运行的任务。 在这里,我做了什么。

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。 推荐的方法是什么?

谢谢。

我以为我在这里回答你的问题。 如果您需要更多示例代码来说明如何使用Task Parallel Library执行此操作,请使用CancellationTokenSourceIProgress<T> ,这里是:

 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<int>((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) { if (this._cancelWork != null) this._cancelWork(); } private int DoWork( int limit, CancellationToken token, IProgress<int> 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 )和报告UI线程(通过WorkerReportsProgress )的进度。

请参阅这里的优秀的详细文章 – 如何使用BackgroundWorker 。