wpf 如何在wpf后台执行任务同时能够提供报告并允许取消?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/21348125/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to execute task in the wpf background while able to provide report and allow cancellation?
提问by Syaiful Nizam Yahya
I want to execute a long running task after clicking a wpf button. Here what I did.
单击 wpf 按钮后,我想执行长时间运行的任务。这是我所做的。
private void Start(object sender, RoutedEventArgs e)
{
for (int i = 0; i < 10; i++)
{
Thread.Sleep(2000); // simulate task
}
}
Problem is, this will make wpf gui unresponsive. I also would like to allow cancellation and report progress every 1 second. I expand the code as below.
问题是,这会使 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;
}
My target platform is .NET 4.5. What is the recommended way to do this?
我的目标平台是 .NET 4.5。推荐的方法是什么?
Thanks.
谢谢。
回答by noseratio
I thought I answered your question here. If you need more sample code on how to do this using Task Parallel Library, with CancellationTokenSourceand IProgress<T>, here it is:
我想我在这里回答了你的问题。如果您需要有关如何使用任务并行库执行此操作的更多示例代码,请使用CancellationTokenSource和IProgress<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)
{
this._cancelWork?.Invoke();
}
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;
}
回答by Rohit Vats
BackgroundWorkeris what you are looking for instead of DispatcherTimer.
BackgroundWorker是您正在寻找的,而不是 DispatcherTimer。
It provides support of Cancellation (via WorkerSupportsCancellation) and reporting progress back on UI thread (via WorkerReportsProgress).
它提供对取消的支持(通过WorkerSupportsCancellation)并在 UI 线程上报告进度(通过WorkerReportsProgress)。
Refer to excellent detailed article here - How to Use BackgroundWorker.
请参阅此处的优秀详细文章 -如何使用 BackgroundWorker。

