Member 8010354 Ответов: 2

Как вставить индикатор выполнения При копировании изображений с помощью count


Привет Команда,

Я хотел бы вставить индикатор выполнения при загрузке файла (с подсчетом) и при копировании изображений (с подсчетом).

ВО ВРЕМЯ ЗАГРУЗКИ ФАЙЛА:

private void button1_Click(object sender, EventArgs e)
        {
            OpenFileDialog dlg = new OpenFileDialog();
            //dlg.ShowDialog();

            if (dlg.ShowDialog() == DialogResult.OK)
            {
                string fileName;
                fileName = dlg.FileName;
                using (StreamReader sr = new StreamReader(fileName))
                {
                    while ((line = sr.ReadLine()) != null)
                    {
                        listBox1.Items.Add(line);
                        string[] findingparent = line.Split(',');
                        if (line.Contains(",Y,,") == true)
                        {
                            parents.Add(findingparent[0], ",Y,,," + findingparent[findingparent.Length - 1]);
                            parentcount++;
                        }
                        else
                        {
                            parents.Add(findingparent[0], ",,,,");
                            childcount++;
                        }
                            
                    }
                    sr.Close();
                    label6.Text = (listBox1.Items.Count).ToString();
                    label4.Text = parentcount.ToString();
                    label5.Text = childcount.ToString();
                }
            }
        }


ПРИ КОПИРОВАНИИ ИЗОБРАЖЕНИЙ:

     if (!int.TryParse(textBox3.Text, out int thresholdValue) || thresholdValue < 1)
            {
                // TODO: Display an error message to the user
                return;
            }

            string source = textBox1.Text;
            string destination = textBox2.Text;
            int totalFileCount = 0;
            int currentSubFolder = 0;
            int remainingFileCount = 0;
            string destinationFolder = null;

            ISet<string> extensions = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
{
    ".tif",
    ".tiff",
    ".jpg",
    ".jpeg"
};

            IEnumerable<string> files = Directory
                .EnumerateFiles(source, "*", SearchOption.AllDirectories)
                .Where(f => extensions.Contains(Path.GetExtension(f)));

            foreach (string sourceFile in files)
            {
                if (remainingFileCount == 0)
                {
                    // First file, or the sub-folder is full:
                    currentSubFolder++;
                    destinationFolder = Path.Combine(destination, currentSubFolder.ToString("D3"));
                    if (!Directory.Exists(destinationFolder)) Directory.CreateDirectory(destinationFolder);
                    remainingFileCount = thresholdValue;
                }

                string destinationFile = Path.Combine(destinationFolder, Path.GetFileName(sourceFile));
                File.Copy(sourceFile, destinationFile);
                totalFileCount++;
                remainingFileCount--;   
            }

            MessageBox.Show("All " + totalFileCount + " files are copied");


Что я уже пробовал:

Я попытался добавить индикатор выполнения в щелчок кнопки копирования, где файлы начинают копировать, но я не смог заставить индикатор выполнения работать над ним

Попробовал также приведенный ниже код, но не работает:
pBar.Location = new System.Drawing.Point(20, 20);
          pBar.Width = 200;
          pBar.Height = 30;
          pBar.Name = "progressBar1";
          pBar.Dock = DockStyle.Bottom;
          pBar.Value = totalFileCount;
          this.Text = "Progress: " + totalFileCount.ToString() + "%";

2 Ответов

Рейтинг:
2

OriginalGriff

Проблема в том, что вы зацикливаетесь в потоке пользовательского интерфейса.

Когда вы запускаете приложение, у него есть один поток - поток пользовательского интерфейса, который обрабатывает все обновления дисплея с помощью событий. Если ваш обработчик событий - в этом случае button1_Click циклически проходя через файл, добавляя строки в списки, копируя файлы и т. д., и занимая достаточно времени, чтобы необходим был индикатор выполнения, тогда один поток занят в течение значительного времени. Поскольку он может делать только одну вещь одновременно, он не может реагировать на события, которые обновляют элементы управления экрана, пока ваш обработчик не выйдет. Так что даже индикатор выполнения здесь не очень полезен, так как поток, который обновляет его на экране пользователей, занят копированием файлов!

Решение состоит в том, чтобы переместить долго работающий код во второй поток, освобождая поток пользовательского интерфейса для обновления отображения.
Это может усложниться, потому что только потоку пользовательского интерфейса разрешен доступ к любым элементам управления (включая элементы управления ListBox и ProgressBar), поэтому вам придется вызвать такой код обратно в поток пользовательского интерфейса.

Однако существует довольно простое в использовании решение: Класс BackgroundWorker (System.ComponentModel) | Microsoft Docs[^] позволяет сообщать о прогрессе обратно в поток пользовательского интерфейса, который может обновлять списки, индикаторы выполнения и т. д.

private void FrmMain_Shown(object sender, EventArgs e)
    {
    BackgroundWorker work = new BackgroundWorker();
    work.WorkerReportsProgress = true;
    work.DoWork += Work_DoWork;
    work.ProgressChanged += Work_ProgressChanged;
    work.RunWorkerCompleted += Work_RunWorkerCompleted;
    work.RunWorkerAsync();
    }

private void Work_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
    {
    // Do whatever is necessary after worker complete
    }

private void Work_ProgressChanged(object sender, ProgressChangedEventArgs e)
    {
    // Do display updates as files get copied
    }

private void Work_DoWork(object sender, DoWorkEventArgs e)
    {
    // Do the actual file copy and use ReportProgress to update the display.
    }


Рейтинг:
1

Sandeep Mewara

Здесь должно помочь следующее руководство: Установите значение, отображаемое элементом управления ProgressBar - Windows Forms .NET Framework | Microsoft Docs[^]

Пример, когда индикатор выполнения увеличивается на фиксированное значение:

public void loadFiles()  
{  
   // Sets the progress bar's minimum value to a number representing  
   // no operations complete -- in this case, no files read.  
   progressBar1.Minimum = 0;  
   // Sets the progress bar's maximum value to a number representing  
   // all operations complete -- in this case, all five files read.  
   progressBar1.Maximum = 5;  
   // Sets the Step property to amount to increase with each iteration.  
   // In this case, it will increase by one with every file read.  
   progressBar1.Step = 1;  

   // Uses a for loop to iterate through the operations to be  
   // completed. In this case, five files are to be copied into memory,  
   // so the loop will execute 5 times.  
   for (int i = 0; i <= 4; i++)  
   {  
      // Inserts code to copy a file  
      progressBar1.PerformStep();  
      // Updates the label to show that a file was read.  
      label1.Text = "# of Files Read = " + progressBar1.Value.ToString();  
   }  
}

Пример, когда индикатор выполнения увеличивается на динамическое значение:
public void readFiles()  
{  
   // Sets the progress bar's minimum value to a number
   // representing the hard disk space before the files are read in.  
   // You will most likely have to set this using a system call.  
   // NOTE: The code below is meant to be an example and
   // will not compile.  
   progressBar1.Minimum = AvailableDiskSpace();  
   // Sets the progress bar's maximum value to a number
   // representing the total hard disk space.  
   // You will most likely have to set this using a system call.  
   // NOTE: The code below is meant to be an example
   // and will not compile.  
   progressBar1.Maximum = TotalDiskSpace();  

   // Uses a for loop to iterate through the operations to be  
   // completed. In this case, five files are to be written  
   // to the disk, so it will execute the loop 5 times.  
   for (int i = 1; i<= 5; i++)  
   {  
      // Insert code to read a file into memory and update file size.  
      // Increases the progress bar's value based on the size of
      // the file currently being written.  
      progressBar1.Increment(FileSize);  
      // Updates the label to show available drive space.  
      label1.Text = "Current Disk Space Used = " + progressBar1.Value.ToString();  
   }  
}