C# C-从线程更新windows窗体元素

C# C-从线程更新windows窗体元素,c#,windows,multithreading,forms,C#,Windows,Multithreading,Forms,我目前正在创建一个将笔记本电脑备份到U盘的程序。我创建了一个类,从中调用方法。然后,我通过一个单独的线程启动实际备份。目前,我正试图通过这个线程更改一个文本框和一个进度条。但是,它始终仅在程序运行完毕后立即显示第一次更改,而仅显示其他进度。 我从互联网上尝试了几种解决方案,但到目前为止没有任何效果。也许有人能解决这个问题 backup sales_backup = new backup(); //Start Backup Button private void back

我目前正在创建一个将笔记本电脑备份到U盘的程序。我创建了一个类,从中调用方法。然后,我通过一个单独的线程启动实际备份。目前,我正试图通过这个线程更改一个文本框和一个进度条。但是,它始终仅在程序运行完毕后立即显示第一次更改,而仅显示其他进度。 我从互联网上尝试了几种解决方案,但到目前为止没有任何效果。也许有人能解决这个问题

    backup sales_backup = new backup();

    //Start Backup Button
    private void backup_button_Click(object sender, EventArgs e)
    {
        Thread backupprocess = new Thread(new 
        ThreadStart(sales_backup.backup_start));
        backupprocess.Start();
    }

    //Backup Function
        public void backup_start()
        {
            files_to_copy = 0;
            files_copied = 0;

            var principalForm = System.Windows.Forms.Application.OpenForms.OfType<Form1>().FirstOrDefault();

            if (principalForm.drive_selector.SelectedItem != null)
            {
                //Set Parameters
                principalForm.backup_button.Visible = false;
                error_copy = false;
                error_message = "";
                device_removed = false;

                //Fill variables
                string temp = principalForm.drive_selector.SelectedItem.ToString();
                temp = regex_matching_return_match(temp, @"[A-Z,a-z](:\\)");
                backup_device = temp;

                //Set Backup device size
                for (int i = 0; i < backup_devices_list.Count; i++)
                {
                    if (backup_devices_list[i].backup_device_name == temp)
                    {
                        backup_device_size = backup_devices_list[i].device_size;
                        file_system = backup_devices_list[i].file_system;
                        double temp_free = calculate_GB(backup_devices_list[i].device_free_space.ToString());
                        device_free_space = temp_free;
                        break;
                    }
                }

                //If no device is initialized
                if (backup_device == null || backup_device_size == 0)
                {
                    write_to_textbox(get_create_usb_instance_error(), "red");
                }
                else //If select ist successfull
                {
                    //Get Backup size
                    get_size();
                    if (backup_size < device_free_space)
                    {
                        backup_path_target = backup_device + "\\Backup\\";
                        Directory.CreateDirectory(backup_path_target);

                        //Get file count
                        get_file_count();

                        //Create Copy job
                        for (int i = 0; i < backup_path_source.Length; i++)
                        {
                            string backup_path_s = backup_path_source[i] + "\\";
                            string backup_path_t = backup_path_target + backup_path_target_folders[i] + "\\";
                            copy_function(backup_path_s, backup_path_t);
                            int progress = return_progress();
                            TextBox test = principalForm.textBox2;
                            ProgressBar progress_bar = principalForm.progressBar1;
                            //Delegate Textbox
                            if (test.InvokeRequired)
                            {
                                test.Invoke(new Action(() => test.Text = "Copying: " + backup_path_t));
                            }
                            else
                            {
                                test.Text = "Copying: " + backup_path_t;
                            }
                            //Delegate Progressbar
                            if (progress_bar.InvokeRequired)
                            {
                                test.Invoke(new Action(() => progress_bar.Value = progress));
                            }
                            else
                            {
                                progress_bar.Value = progress;
                            }
                        }

确保从正确的线程执行更新。GUI只能从自己的线程更新。更多。

您是否尝试过使用progress\u bar.InvokeMethodInvoker=>progress\u bar.Value=progress

我无法测试这一点,但它至少可以帮助您实现这一目标:

private void InvokeIfRequired<C>(C control, Action<C> action) where C : Control
{
    if (control.InvokeRequired)
    {
        control.Invoke((Action)(() => action(control)));
    }
    else
    {
        action(control);
    }
}

private void backup_button_Click(object sender, EventArgs e)
{
    var principalForm = System.Windows.Forms.Application.OpenForms.OfType<Form1>().FirstOrDefault();
    if (principalForm.drive_selector.SelectedItem != null)
    {
        principalForm.backup_button.Visible = false;

        string temp = principalForm.drive_selector.SelectedItem.ToString();

        TextBox test = principalForm.textBox2;
        ProgressBar progress_bar = principalForm.progressBar1;

        Action<string> updateTest = t => this.InvokeIfRequired<TextBox>(test, c => c.Text = t);
        Action<int> updateProgress = v => this.InvokeIfRequired<ProgressBar>(progress_bar, c => c.Value = v);

        Thread backupprocess = new Thread(new ThreadStart(() => sales_backup.backup_start(temp, updateTest, updateProgress)));
        backupprocess.Start();
    }
}

//Backup Function
public void backup_start(string temp, Action<string> updateTest, Action<int> updateProgress)
{
    files_to_copy = 0;
    files_copied = 0;

    //Set Parameters

    error_copy = false;
    error_message = "";
    device_removed = false;

    //Fill variables
    temp = regex_matching_return_match(temp, @"[A-Z,a-z](:\\)");
    backup_device = temp;

    //Set Backup device size
    for (int i = 0; i < backup_devices_list.Count; i++)
    {
        if (backup_devices_list[i].backup_device_name == temp)
        {
            backup_device_size = backup_devices_list[i].device_size;
            file_system = backup_devices_list[i].file_system;
            double temp_free = calculate_GB(backup_devices_list[i].device_free_space.ToString());
            device_free_space = temp_free;
            break;
        }
    }

    //If no device is initialized
    if (backup_device == null || backup_device_size == 0)
    {
        write_to_textbox(get_create_usb_instance_error(), "red");
    }
    else //If select ist successfull
    {
        //Get Backup size
        get_size();
        if (backup_size < device_free_space)
        {
            backup_path_target = backup_device + "\\Backup\\";
            Directory.CreateDirectory(backup_path_target);

            //Get file count
            get_file_count();

            //Create Copy job
            for (int i = 0; i < backup_path_source.Length; i++)
            {
                string backup_path_s = backup_path_source[i] + "\\";
                string backup_path_t = backup_path_target + backup_path_target_folders[i] + "\\";
                copy_function(backup_path_s, backup_path_t);
                int progress = return_progress();

                //Delegate Textbox
                updateTest("Copying: " + backup_path_t);

                //Delegate Progressbar
                updateProgress(progress);
            }
        }
    }
}

无法从后台线程更新UI。如果使用async/await和Process类向其他线程报告进度,则也不需要调用。如果使用Task.Run和async/await,则不必使用Invoke。。如果UI线程忙,则调用自身块。您也应该将UI与文件处理代码分开—当您可以将驱动器等作为方法参数传递时,不需要像这样访问主窗体。这不是答案。应该删除它。请获得50个代表点以发表评论。更改代理类型不会更改调用的内容。代码可以是progress\u bar.Invoke=>progress\u bar.Value=progress;。