繁体   English   中英

如何在进程等待完成时显示加载控件?

[英]How can I display a loading control while a process is waiting for be finished?

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

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

打开和关闭时,这在单个请求中将属性“Active”更改为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;
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM