在 Windows 窗体应用程序中显示加载指示器





5.00/5 (6投票s)
本文介绍了如何在 Windows Forms 应用程序中显示加载指示器(GIF 图像),当后台执行一些长时间运行的任务时。
引言
如果您的 Windows Form 应用程序正在后台执行一些长时间运行的任务,那么用户界面会变得无响应。 为了告知用户某些长时间运行的任务正在后台运行,您需要显示一个指示器。 该指示器可以像动画图像(GIF 图像)一样简单。 本文介绍如何在 Windows Forms 中执行相同的操作。
本文提供的示例显示了文本文件中存在的元音、辅音、数字和特殊字符的数量。 它逐行读取用户提供的文本文件中的输入,并在网格中显示输出。
设计窗体
在 Visual Studio 中创建一个新的 Windows Form 项目。

将 Label、Button、ComboBox 和 DataGridView 控件拖放到 Windows Form 中,以创建一个类似于下面显示的窗体

将 PictureBox 控件添加到窗体中心,然后将“Image”和“InitialImage”属性设置为加载图像。 您可以从 Visual Studio 属性窗口导入图像。 为此,请单击“初始图像”值旁边显示的“...”按钮。 这将打开“选择资源”窗口。 选择“项目资源文件”选项,然后单击“导入...”按钮。 选择加载图像,然后单击“打开”和“确定”按钮。 重复相同的过程来设置 PictureBox 控件的“Image”属性。 请参考下图。

核心功能
当用户单击“查找”按钮时,我们希望向用户显示一个加载指示器,以便用户可以知道该操作正在后台进行。 加载指示器显示如下

后台操作完成后,加载图像将被隐藏,并将数据加载到网格中。 下面是将数据加载到网格中的窗体的屏幕截图。

Using the Code
显示对话框
当用户单击“浏览..”按钮时,我们希望显示一个对话框,从中选择文本文件。 以下代码用于显示具有自定义设置的文件打开对话框。 注意添加到文件打开对话框的“Title”和“Filter”。
var dialog = new OpenFileDialog();
dialog.Title = "Browse Text Files";
dialog.DefaultExt = "txt";
dialog.CheckFileExists = true;
dialog.Filter = "Text files (*.txt)|*.txt|All files (*.*)|*.*";
dialog.Multiselect = false;
dialog.ShowDialog();
var fileName = dialog.FileName;
txtFilePath.Text = fileName;
显示加载指示器
private void SetLoading(bool displayLoader)
{
    if (displayLoader)
    {
        this.Invoke((MethodInvoker)delegate
        {
            picLoader.Visible = true;
            this.Cursor = System.Windows.Forms.Cursors.WaitCursor;
        });
    }
    else
    {
        this.Invoke((MethodInvoker)delegate
        {
            picLoader.Visible = false;
            this.Cursor = System.Windows.Forms.Cursors.Default;
        });
    }
}
上面的代码用于显示保存在 PictureBox 控件中的加载图像。 请注意,该代码保存在 this.Invoke(); 内部。 显示加载图像时,光标将更改为“wait”光标。
释放 UI 线程
为了保持 UI 的响应性,整个操作在一个新线程中进行。
private void btnFind_Click(object sender, EventArgs e)
{
    try
    {
        Thread threadInput = new Thread(DisplayData);
        threadInput.Start();
    }
    catch (Exception ex)
    {
        DisplayError(ex);
    }
}
DisplayData() 方法执行所有操作,例如调用方法来显示/隐藏加载图像、从文件读取、查找字符和绑定网格。
private void DisplayData()
{
    SetLoading(true);
    
    // Do other operations...
    SetLoading(false);
}
第一行显示加载指示器。 下一步执行其他操作,最后隐藏加载指示器。
从控件读取数据
我们无法直接从控件读取数据,因为整个操作是在一个单独的线程中进行的。 如果您尝试直接从控件读取内容,则会引发错误。
如果您尝试直接在 DisplayData() 方法中读取 ComboBox 值,则会引发无效的跨线程操作错误。
var charType = cmbCharacterType.Text;
InvalidOperationException跨线程操作无效:从创建控件的线程以外的线程访问控件“cmbCharacterType”。
从控件读取数据的方式如下
this.Invoke((MethodInvoker)delegate
{
    charType = cmbCharacterType.Text;
                    
    path = txtFilePath.Text.Trim();
});
历史
- 2017 年 12 月 7 日:初始版本


