搜索按钮上的ProgressBar

时间:2018-08-23 10:53:10

标签: c# multithreading winforms progress-bar

我有以下C#代码显示进度条:

{
    public partial class FormPesquisaFotos : Form
    {
        public FormPesquisaFotos()
        {
            InitializeComponent();
        }

        private void FormPesquisaFotos_Load(object sender, EventArgs e)
        {
        }

        private void button1_Click(object sender, EventArgs e)
        {
            //Mostra a barra de progresso da pesquisa
            while (progressBar1.Value < 100)
            progressBar1.Value += 1;
            {
                //Criar um objeto (instância, cópia) da classe FormResultadosFotos
                FormResultadosFotos NovoForm = new FormResultadosFotos();
                NovoForm.Show();
            }
        }
    }
}

它仅在搜索结束时加载(单击按钮后)。如何在搜索开始时运行进度条?

这是在新表格上显示结果的代码。进度栏停止在95%,几秒钟后显示结果。

{
    public partial class FormResultadosFotos : Form
    {
        public FormResultadosFotos()
        {
            InitializeComponent();
        }
        private void FormFotos_Load(object sender, EventArgs e)
        {
            // se pretendermos pesquisar em várias pastas
            List<string> diretorios = new List<string>()
            {@"\\Server\folder01\folder02"};

            // se pretendermos pesquisar as várias extensões
            List<string> extensoes = new List<string>()
    {".jpg",".bmp",".png",".tiff",".gif"};

            DataTable table = new DataTable();
            table.Columns.Add("Nome e formato do ficheiro (duplo clique para visualizar a imagem)");
            table.Columns.Add("Caminho ( pode ser copiado Ctrl+C )");
            foreach (string diretorio in diretorios)
            {
                var ficheiros = Directory.EnumerateFiles(diretorio, "*", SearchOption.AllDirectories).
                    Where(r => extensoes.Contains(Path.GetExtension(r.ToLower())));
                foreach (var ficheiro in ficheiros)
                {
                    DataRow row = table.NewRow();
                    row[0] = Path.GetFileName(ficheiro);
                    row[1] = ficheiro;
                    table.Rows.Add(row);
                }
            }
            dataGridView1.DataSource = table;
            dataGridView1.Columns[1].Visible = true;
        }
        private void dataGridView1_DoubleClick(object sender, EventArgs e)
        {
            FormPictureBox myForm = new FormPictureBox();
            string imageName = dataGridView1.CurrentRow.Cells[1].Value.ToString();
            Image img;
            img = Image.FromFile(imageName);
            myForm.pictureBox1.Image = img;
            myForm.ShowDialog();
        }
    }
}

谢谢。

2 个答案:

答案 0 :(得分:2)

您在这里描述的是一个多线程问题。 您的循环在UI有机会更新之前运行。

您应该查看https://stephenhaunts.com/2014/10/14/using-async-and-await-to-update-the-ui-thread/,以获取有关在循环中如何更新UI的说明和示例。

致谢

答案 1 :(得分:2)

您必须在新线程而不是主线程上拥有它。

这是一个小例子:

private void buttonWorkerTest_Click(object sender, RoutedEventArgs e)
{
    this.progressBarWorkerTest.Value = 0;
    BackgroundWorker worker = new BackgroundWorker();
    // Event for the method that will run on the background
    worker.DoWork += this.Worker_DoWork;
    // Event that will run after the BackgroundWorker finnish
    worker.RunWorkerCompleted += this.Worker_RunWorkerCompleted;
    worker.RunWorkerAsync();


}

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    for (int i = 1; i <= 100; i++)
    {
        Dispatcher.Invoke(new Action(() =>
        {
            this.progressBarWorkerTest.Value = i;
        }));
        Thread.Sleep(100);
    }
}

private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // You can put the code here to open the new form and such
}

Dispacher.Invoke是因为它在WPF上,对于WinForm,只需将其更改为this.Invoke

此示例是,单击按钮后将启动BackgroundWorker,将for设置为1到100,它将休眠100毫秒并更新进度条。

希望这会有所帮助

编辑

现在在示例中包括了在BackgroundWorker完成时运行的事件,以防万一是否需要

编辑2:

我的建议是,在背景上搜索照片时,将它们全部插入到DataTable中,因为您已经准备好搜索它们并且可以在此处完成工作,然后只需在FormResultadosFotos上构造一个构造函数即可接收到数据表。

根据我的理解,主要目标是以FormPesquisaFotos形式搜索它们(这就是为什么我们在那里有背景工作人员进行搜索并更新ProgressBar的原因),并以新的形式AKA FormResultadosFotos显示它们。 >

// Lets create a DataTable variable to be access on the Worker_DoWork and then on the Worker_RunWorkerCompleted
private DataTable tableOfPhotos;

private void Worker_DoWork(object sender, DoWorkEventArgs e)
{
    // Search for the photos here and then add them to the DataTable
    this.tableOfPhotos = new DataTable();
    tableOfPhotos.Columns.Add("Nome e formato do ficheiro (duplo clique para visualizar a imagem)");
    tableOfPhotos.Columns.Add("Caminho ( pode ser copiado Ctrl+C )");
    foreach (string diretorio in diretorios)
    {
        // se pretendermos pesquisar em várias pastas
        List<string> diretorios = new List<string>()
        {@"\\Server\folder01\folder02"};

        // se pretendermos pesquisar as várias extensões
        List<string> extensoes = new List<string>()
        {"*.jpg","*.bmp","*.png","*.tiff","*.gif"};

        var ficheiros = Directory.EnumerateFiles(diretorio, "*", SearchOption.AllDirectories).
            Where(r => extensoes.Contains(Path.GetExtension(r.ToLower())));
        foreach (var ficheiro in ficheiros)
        {
            DataRow row = tableOfPhotos.NewRow();
            row[0] = Path.GetFileName(ficheiro);
            row[1] = ficheiro;
            tableOfPhotos.Rows.Add(row);
        }
    }
}

private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
    // You can put the code here to open the new form and such
    FormResultadosFotos NovoForm = new FormResultadosFotos(this.tableOfPhotos);
    NovoForm.Show();
}


// Constructor that will receive the DataTable and put it into the dataGridView1, it should be added on the Form FormResultadosFotos
Public FormResultadosFotos(DataTable table)
{
    InitializeComponent();
    // In here we will tell the where is the source for the dataGridView1
    this.dataGridView1.DataSource = table;
}

在这里,您还可以通过在行this.dataGridView1.DataSource = table;上放置一个断点来查看表的含义,如果表为空,则表中没有任何内容(也许目录中没有照片?可以吗?不能访问它吗?不在工作并且没有任何IDE,只是根据我脑海中的想法而定,但是如果需要,您也可以将文件保存在模拟代码中:

List<string> tempList = new List<string>;
foreach (string entryExt in extensoes)
{
    foreach (string entryDir in diretorios)
    {
        //  SearchOption.AllDirectories search the directory and sub directorys if necessary
        // SearchOption.TopDirectoryOnly search only the directory
        tempList.AddRange(Directory.GetFiles(entryDir, entryExt, SearchOption.AllDirectories));
    }
}

// Here would run all the files that it has found and add them into the DataTable
foreach (string entry in tempList)
{
    DataRow row = tableOfPhotos.NewRow();
    row[0] = Path.GetFileName(entry);
    row[1] = entry;
    tableOfPhotos.Rows.Add(row);
}

编辑3:

更改代码

List<string> extensoes = new List<string>(){".jpg",".bmp",".png",".tiff",".gif"};

List<string> extensoes = new List<string>(){"*.jpg","*.bmp","*.png","*.tiff","*.gif"};

您需要在扩展名前加*(例如.png)来搜索该扩展名的文件