Инкремент ProgressBar в другом классе

1

это мой первый вопрос, который я задаю здесь, поэтому, пожалуйста, будьте осторожны со мной;)

Таким образом, у меня на самом деле есть два WinForms в моем приложении С#, которое я пишу в данный момент (я довольно новичок в С#).

В этом окне есть кнопка, которая сохраняет фотографии с устройства USB, выбранного ранее в списке, в другую папку. После нажатия этой кнопки мой основной поток, конечно, занят копированием, поэтому я решил создать еще один WinForm, который содержит мой ProgressBar.

Foreach завершена копия, я хочу увеличить свой ProgressBar соответственно.

Поэтому я подсчитываю количество копий, которые мне нужно сделать, и даю ему максимальную производительность. Но моя проблема на данный момент заключается в том, что я действительно не знаю, как увеличить ProgressBar, не получив исключение Thread Unsafe.

Здесь мой код ProgressWindow:

public partial class ProgressWindow : Form
{
    BackgroundWorker updateProgressBarThread = new BackgroundWorker();

    private Boolean _isThreadRunning = false;
    public Boolean IsThreadRunning
    {
        get { return _isThreadRunning; }
        set { _isThreadRunning = value; }
    }

    private int _progressbarLength;
    public int ProgressbarLength
    {
        get { return _progressbarLength; }
        set { _progressbarLength = value; }
    }

    private int progress = 1;

    public ProgressWindow()
    {
        Show();
        InitializeComponent();
    }

    private void StartUpdateThread(object sender, DoWorkEventArgs e)
    {
        BackgroundWorker worker = sender as BackgroundWorker;

        // Reports progress to the ProgressChangedEvent function. (Thread Safe)

    }

    private void FinishProgressThread(object sender, RunWorkerCompletedEventArgs e)
    {
        if (!_isThreadRunning)
        {
            MessageBox.Show("Erfolgreich kopiert");
            Close();
        }

    }

    private void ProgressChangedEvent(object sender, ProgressChangedEventArgs e)
    {
        this.copyProgressbar.Value = e.ProgressPercentage;
        this.progressStatus.Text = e.ProgressPercentage.ToString();
    }

    public void CallUpdateThread()
    {
        updateProgressBarThread.WorkerReportsProgress = true;

        updateProgressBarThread.DoWork += new DoWorkEventHandler(StartUpdateThread);
        updateProgressBarThread.ProgressChanged += new ProgressChangedEventHandler(ProgressChangedEvent);
        updateProgressBarThread.RunWorkerCompleted += new RunWorkerCompletedEventHandler(FinishProgressThread);
        updateProgressBarThread.RunWorkerAsync();
    }

}

Я хочу увеличить свой ProgressBar с помощью 1 после каждой успешной копии. Как это сделать из основного потока?

Это функция, которая фактически обрабатывает процесс копирования

private void SaveFile(System.IO.DirectoryInfo root)
{
    try
    {
        IEnumerable<DirectoryInfo> directoriesNames = root.EnumerateDirectories();

        // New instance of thread ProgressWindow.
        ProgressWindow progress = new ProgressWindow();
        progress.CallUpdateThread();

        foreach (DirectoryInfo element in directoriesNames)
        {
            // Query all subdirectories and count everything with the in the configuration made settings.
            if (!element.Attributes.ToString().Contains("System"))
            {
                // Now we insert the configuration we applied.
                String fileExtension = null;

                if (Properties.Settings.Default._configPhoto)
                {
                    fileExtension = "*.jpg";
                }

                if (Properties.Settings.Default._configWordDocument)
                {
                    fileExtension = "*.odt";
                }

                FileInfo[] jpgList = element.GetFiles(fileExtension, SearchOption.AllDirectories);

                // set the size of the progress bar
                progress.ProgressbarLength = jpgList.Count();

                // Now we go through all our results and save them to our backup folder.
                foreach (FileInfo tmp in jpgList)
                {
                    string sourceFilePath = tmp.FullName;
                    string destFilePath = PATHTOBACKUP + "\\" + tmp.Name;
                    progress.IsThreadRunning = true;

                    try
                    {                                
                        System.IO.File.Copy(sourceFilePath, destFilePath, true);
                    }
                    catch (IOException ioe)
                    {
                        MessageBox.Show(ioe.Message);
                    }
                }
            }
        }
        // progress.IsThreadRunning = false;
    }
    catch (UnauthorizedAccessException e)
    {
        MessageBox.Show(e.Message);
    }
}

Это довольно очевидно, что я должен сделать это после этой функции

System.IO.File.Copy(sourceFilePath, destFilePath, true);

Но как я могу сообщить об этом моему ProgressWindow?

Я очень надеюсь, что я объясню это достаточно хорошо, не уверен, что у меня что-то важное.

Спасибо заранее, ребята

  • 0
    Копирование в потоке пользовательского интерфейса? почему вы не обрабатываете копирование в фоновом режиме?
  • 0
    Почему я должен ? Это элемент другого оконного класса, и я строго хочу отделить свою логику от моего окна прогресса, которое я мог бы использовать несколько раз, не только при копировании
Показать ещё 3 комментария
Теги:
multithreading
winforms
backgroundworker

1 ответ

1
Лучший ответ

Вот компактный пример ключевых компонентов:

  • Нажатие кнопки запускает новый поток
  • Прогресс выполняется по длине файла, а не по количеству файлов
  • BeginInvoke используется для обновления индикатора выполнения (исключая исключение Cross Thread)

        ProgressBar pb = new ProgressBar() { Minimum = 0, Maximum = 100 };
        Button btn = new Button();
        btn.Click += delegate {
            Thread t = new Thread(() => {
                DirectoryInfo dir = new DirectoryInfo("C:\\temp\\");
                var files = dir.GetFiles("*.txt");
                long totalLength = files.Sum(f => f.Length);
                long length = 0;
                foreach (var f in files) {
                    length += f.Length;
                    int percent = (int) Math.Round(100.0 * length / totalLength);
                    pb.BeginInvoke((Action) delegate {
                        pb.Value = percent;
                    });
    
                    File.Copy(f.FullName, "...");
                }
            });
            t.IsBackground = true;
            t.Start();
        };
    

Ещё вопросы

Сообщество Overcoder
Наверх
Меню