打开电脑,突然想起来,昨天下午,有位仁兄和我讨论过一个事,不妨拿来说说。
她说她的 牛逼程序要处理一堆东东,要弄个进度条作提示,不过进度条是在另一个窗口中的,她的想法是,在开 始处理数据时弹出进度对话框,实时显示处理进度,当处理完成后关闭对话框。乍看起来其实不难,不 过她遇到了以下问题,故在群里提问。
1、模态对话框的问题。
这问题好办,一般来说, 要长时间来处理数据,应该考虑后台异步操作,用砖家的话讲就是多线程。不过她在显示窗口时调用了 ShowDialog方法,这样代码会一直停在那里,直到窗口关闭。
如果是异步操作,通常来说,在启 动后台任务后会马上返回,这么一来,只要把代码的顺序调一下就可以解决这问题,先启动后台任务, 再调用ShowDialog方法,这样一来,就算代码停在ShowDialog那里也不会影响后台任务的执行。
2、如何控制其他窗口中控件。
可以在在窗口类中定义公共方法来对控件进行某些操作, 之后在其他地方就可以通过这些公共方法来调控。如果是跨线程调用,应当考虑使用委托或事件来调用 。不然你学了委托和事件干吗呢?
另一种方法就是直接把进度窗口中的ProgressBar控件声明为 public,这样其他类就可以轻松访问了。
3、后台任务如何更简单。
方法是灵活的,有很 多种。最简单的是利用.NET 4.5和C# 5.0 中的新特性,这种方法肯定是最简单的。第二种则是使用.NET 4 中新加的Task类来调度线程;比较传统,在2.0时代用得最多的方法是直接用Thread类。
但是 ,有一个组件是专为后台任务而开放的,忘了没有?——BackgroundWorker,也许有些朋友是忘了这个 组件了。现在很多人就是这样,有了小三就忘了结发妻子,我们众多码农也是这样,常常会忘本。
既有后台任务,又要报告进度,用BackgroundWorker不是更合适吗?于是我问了她两遍:“还记 得吗?” 果然不出我所料,记不起来了,呵呵。
说了那么多,估计需要实例才能解决问题,好 吧,上菜。
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows.Forms; using System.IO; namespace MyApp { public partial class Form1 : Form { static string SaveDir = string.Empty; private FormProgress fpro = null; public Form1() { InitializeComponent(); fpro = new FormProgress(); } private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { int fileCount = Convert.ToInt32(e.Argument); Random rand = new Random(); byte[] buffer = new byte[2048]; for (int i = 0; i < fileCount; i++) { try { string fileName = Path.Combine(SaveDir, i.ToString() + ".tmp"); using (var stream = File.Create(fileName)) { int n = 0; int maxByte = 8 * 1024 * 1024; while (n < maxByte) { rand.NextBytes(buffer); stream.Write(buffer, 0, buffer.Length); n += buffer.Length; } } } catch { continue; } finally { // 报告进度 this.backgroundWorker1.ReportProgress(i + 1); } } } private void button1_Click(object sender, EventArgs e) { if (Directory.Exists(SaveDir) == false) { return; } button1.Enabled = false; int cout = Convert.ToInt32(this.nmbud.Value); this.fpro.progressBar1.Minimum = 0; this.fpro.progressBar1.Maximum = cout; this.fpro.progressBar1.Value = this.fpro.progressBar1.Minimum; this.backgroundWorker1.RunWorkerAsync(cout); // 在开始异步操作后ShowDialog // 这样即使代码停在那里也不会影响后台任务的执行 fpro.ShowDialog(this); } private void backgroundWorker1_ProgressChanged(object sender, ProgressChangedEventArgs e) { int val = e.ProgressPercentage; this.fpro.lblText.Text = string.Format("已生成{0}个文件。", val); this.fpro.progressBar1.Value = val; } private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { button1.Enabled = true; fpro.Hide(); MessageBox.Show("操作完成。", "提示", MessageBoxButtons.OK, MessageBoxIcon.Information); } private void btnBrowsFd_Click(object sender, EventArgs e) { FolderBrowserDialog fd = new FolderBrowserDialog(); fd.RootFolder = Environment.SpecialFolder.Desktop; if (DialogResult.OK == fd.ShowDialog()) { SaveDir = fd.SelectedPath; } fd.Dispose(); } } }
以上是小编为您精心准备的的内容,在的博客、问答、公众号、人物、课程等栏目也有的相关内容,欢迎继续使用右上角搜索按钮进行搜索后台
, 方法
, showdialog
, using
, system
, backgroundworker
, 进度
backgroundwork
backgroundworker、c backgroundworker、wpf backgroundworker、backgroundworker用法、多个backgroundworker,以便于您获取更多的相关知识。