首页 > 解决方案 > C# 加载图片框 - Windows 窗体

问题描述

    private void Button_Generate_Click(object sender, EventArgs e)
    {
        pictureBox1.Visible = true;
        Download_xl();
        pictureBox1.Visible = false;

    }

   public void Download_xl()
    {

        string strPath = Application.StartupPath;
        SqlTable sqltbl = new SqlTable();

        saleno = comboBox2.Text;

        FindBaseGradeStaple();
        FindLoanID();

        qry = "Select * from dbname.dbo.vw_SingleSales where saleno = '" +
                saleno + "'";

        if (rs.State == 1) { rs.Close(); }
        rs.Open(qry, sqltbl.GetSqlConnection());

        if (rs.RecordCount > 0)
        {
            Excel.Application xlapp = new Excel.Application();
            Excel.Workbook wkb = xlapp.Workbooks.Open(strPath + @"\Sales_Contract.xlsx");
            Excel.Worksheet wksht = wkb.Sheets["BaleValue"];
            xlapp.Visible = false;

            wksht.Range["A9"].CopyFromRecordset(rs);


            saleno = saleno.Replace(@"/", "-");
            savepath = Application.StartupPath;
            wkb.SaveAs(savepath + @"\Single Sales - " + saleno + ".xlsx", Excel.XlFileFormat.xlWorkbookDefault);
            xlapp.Visible = true;
            }
        else
        {

            MessageBox.Show("No Records for the Saleno - " + saleno);
        }

    }

上面这段代码中的rs是ADODB.Recordset。

在上面的代码中,pictureBox1 在单击按钮后不会立即显示。相反,Download_xl 的一些任务被执行需要一段时间。我想显示图片并同时运行 Download_xl 函数。上面的代码是用 C# 编写的。我看了一下多线程,但由于我对 c# 比较陌生,所以我无法弄清楚。

标签: c#winforms

解决方案


您当前的代码不起作用,因为 UI 线程被Download_xl(). 使用pictureBox1.Refresh()是有效的,因为它强制 UI 元素在阻塞代码开始之前更新。图片框包含的 .GIF 没有动画,因为 UI 线程仍被Download_xl().

你可以让你的事件处理程序async void。在里面,你可以异步等待一个运行的任务Download_xl()。这样做不会在执行任何长时间运行的进程时阻塞您的 UI,但您的图像在Download_xl()完成执行之前不会变得不可见,因为您正在等待await使用关键字执行它的任务。

有关更多信息,请参阅https://docs.microsoft.com/en-us/dotnet/standard/parallel-programming/task-based-asynchronous-programming

private async void Button_Generate_Click(object sender, EventArgs e)
{
    pictureBox1.Visible = true;

    await Task.Run(() => Download_xl());

    pictureBox1.Visible = false;
}

显然,您需要处理Download_xl()可能由您自己引起的任何多线程问题。如果没有看到该方法的代码,没有人可以真正帮助您。

如果您使用我的示例并制作事件处理程序async void,那么您可能想要控制按下它的频率。与您的原始代码不同,这不会阻塞 UI 线程,因此用户可以多次单击,并且每次单击都会启动一个执行的新任务Download_xl()。您可以通过简单的方法来解决这个问题,例如在事件开始时禁用按钮并在结束时重新启用它,或者查看信号量。


关于您的评论,由于您没有提供代码,我看不到您在做什么comboBox1,但是您需要执行类似的操作

comboBox1.Invoke(new Action(() =>
{
    comboBox1.WhateverMethodYoureAlreadyExecuting();
}));

您需要调用,因为Download_xl()现在正在另一个线程上运行(因为我们在任务中执行它)。使用 Invoke 将对 UI 线程上的 UI 元素执行任何操作,并且您的跨线程异常应该消失。

PSDownload_xl()不遵循 C# 命名约定,它应该是DownloadXl()(尽管这仍然不是很有描述性)


推荐阅读