C#WinForms – 如何在进程等待完成时显示加载控件。 我使用“LoadingCircle”和一个线程

我决定使用这个第三方组件在我的Windows窗体中进行简单的加载控制。

http://www.codeproject.com/Articles/14841/How-to-write-a-loading-circle-animation-in-NET

这在开启和关闭时工作正常,在单个请求中将属性“活动”更改为true或false(每次一个)。 问题是当进程等待服务时,我假装在进程启动之前激活loadingControl,当我“认为”该进程必须完成时关闭。 当我这样做时,图像加载显示为静态图像。 (没有动画)。

对不起这个问题,我是C#的新人。 但我认为我需要使用Threads或类似的东西。

所以我的一般代码是这样的:

using [libraries here]...; namespace [namespace here] { Public partial class Form1 : Form { public Form1() { InitializeComponent(); this.loadingCircle1.Visible = false; } private void button1_Click(object sender, EventArgs e) { Thread t = new Thread(new ThreadStart(showLoading)); this.loadingCircle1.Visible = true; t.Start(); //Import an Excel t.Abort(); } public void showLoading() { loadingCircle1.Active = true; loadingCircle1.RotationSpeed = 10; } } } 

但是,加载显示为没有动画的静态图像。

您创建一个线程,它只是设置两个属性,然后结束。 t.Abort可能什么都不做,因为那个时候线程已经退出了。 更糟糕的是,您在UI线程上导入excel文件,该文件会阻止任何动画并冻结整个UI。

这就是你应该如何做到的:

备注:当然,如果您的表单是响应式的,您必须禁用/启用控件并准备好在加载过程中关闭表单时会发生什么情况。

1.使用线程

如果你真的想显式使用线程,那就这样做:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private Thread workerThread = null; private void btnImport_Click(object sender, EventArgs e) { // start the animation (I used a progress bar, start your circle here) progressBar1.Visible = true; progressBar1.Style = ProgressBarStyle.Marquee; // start the job and the timer, which polls the thread btnImport.Enabled = false; workerThread = new Thread(LoadExcel); workerThread.Start(); timer1.Interval = 100; timer1.Start(); } private void LoadExcel() { // some work takes 5 sec Thread.Sleep(5000); } private void timer1_Tick(object sender, EventArgs e) { if (workerThread == null) { timer1.Stop(); return; } // still works: exiting if (workerThread.IsAlive) return; // finished btnImport.Enabled = true; timer1.Stop(); progressBar1.Visible = false; workerThread = null; } } 

2.背景工作者

BackgroundWorker可以在完成时抛出一个事件:

 public partial class Form1 : Form { public Form1() { InitializeComponent(); backgroundWorker1.DoWork += BackgroundWorker1_DoWork; backgroundWorker1.RunWorkerCompleted += BackgroundWorker1_RunWorkerCompleted; } private void btnImport_Click(object sender, EventArgs e) { // start the animation progressBar1.Visible = true; progressBar1.Style = ProgressBarStyle.Marquee; // start the job btnImport.Enabled = false; backgroundWorker1.RunWorkerAsync(); } private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e) { LoadExcel(); } private void BackgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { btnImport.Enabled = true; progressBar1.Visible = false; } private void LoadExcel() { // some work takes 5 sec Thread.Sleep(5000); } } 

3.使用async-await

这是最简单的一个。

 public partial class Form1 : Form { public Form1() { InitializeComponent(); } private async void btnImport_Click(object sender, EventArgs e) { // start the waiting animation progressBar1.Visible = true; progressBar1.Style = ProgressBarStyle.Marquee; // simply start and await the loading task btnImport.Enabled = false; await Task.Run(() => LoadExcel()); // re-enable things btnImport.Enabled = true; progressBar1.Visible = false; } private void LoadExcel() { // some work takes 5 sec Thread.Sleep(5000); } } 

我建议使用async / await(对于C#5.0):

 private void button1_Click(object sender, EventArgs e){ ImportAsync(); } private async Task ImportAsync(){ // UI-thread showLoading(); this.loadingCircle1.Visible = true; // wait until task will be finished await Task.Run(() => { // different non-blocking thread for all the hard work, but without UI-stuff // import an Excel }); // going back to UI-thread this.loadingCircle1.Visible = false; }