c# - C# 使用 task 和 yield 让 UI 了解正在运行的进程
问题描述
编写这样的代码是不好的做法。我想要完成的是用户可以按下控件上的按钮。该按钮启动某种分析过程,并且对于完成的每个项目,它都会向用户显示结果。
private IEnumerable<int> AnalyzeItems() {
for(int i = 0; i < 1000; i++) {
Thread.Sleep(500);
yield return i;
}
}
private void PerformTask_Click(object sender, EventArgs e) {
Task.Run(() => {
foreach (var item in AnalyzeItems()) {
ResultLog.Invoke((Action)delegate() { ResultLog.Text += item.ToString(); });
}
});
}
解决方案
为什么不使用Backgroundworker?
首先将 backgroundworker 属性设置为:
- WorkerReportsProgress = true
- WorkerSupportsCancellation = true
这是代码:
public partial class Form1 : Form {
public Form1() {
InitializeComponent();
}
private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) {
for (int i = 0; i < 1000; i++) {
Thread.Sleep(500);
if (backgroundWorker1.CancellationPending) {
e.Cancel = true;
break;
}
backgroundWorker1.ReportProgress(i / 10, "step " + i);
}
}
private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) {
label1.Text = e.UserState.ToString();
progressBar1.Value = e.ProgressPercentage;
}
private void button1_Click(object sender, EventArgs e) {
cancelButton.Focus();
button1.Enabled = false;
backgroundWorker1.RunWorkerAsync();
}
private void cancelButton_Click(object sender, EventArgs e) {
backgroundWorker1.CancelAsync();
}
private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) {
button1.Enabled = true;
if (e.Error != null) {
MessageBox.Show(e.Error.Message, "Unexpected error");
}
if (e.Cancelled) {
MessageBox.Show("Process stopped by the user", "Cancelled");
}
label1.Text = "Press start";
progressBar1.Value = progressBar1.Minimum;
}
}