Je crée actuellement un programme pour sauvegarder les ordinateurs portables vers un bâton USB. J'ai créé une classe à partir de laquelle je appelle des méthodes. Je commence ensuite la sauvegarde réelle via un fil séparé. Pour le moment, j'essaie de changer une zone de texte et une barre de progression via ce fil. Cependant, il ne montre toujours que le premier changement immédiatement et les autres progrès que lorsque le programme a traversé. J'ai essayé plusieurs solutions d'Internet, mais rien n'a travaillé jusqu'à présent. Peut-être que quelqu'un a une solution ici.
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;
}
}
3 Réponses :
Assurez-vous que vous faites la mise à jour du bon fil. GUI ne peut être mis à jour que de son propre fil. Plus ici . P >
Avez-vous essayé d'utiliser progress_bar.invoke ((méthodalvoke) (() => progres_bar.value = avancement)); code> p>
Ce n'est pas une réponse. Il devrait être supprimé. S'il vous plaît gagner les 50 points REP pour poster des commentaires.
Changer le type de délégué ne changera pas ce qui est invoqué. Le code pourrait être progress_bar.invoke ((() => progress_bar.value = progrès); code>.
Je ne pouvais pas tester cela, mais cela devrait au moins vous aider à y arriver:
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);
}
}
}
}
Vous ne pouvez pas mettre à jour l'interface utilisateur à partir d'un fil d'arrière-plan. Vous pas i> besoin
invoke code> soit, si vous utilisezasync / attendre code> et le processusprocessus code> Signaler des progrès sur d'autres threads Si vous utilisez une tâche
.Run code> etasync / attendre code> Vous n'aurez pas à utiliserinvoke (). Code>. Invoke Blocks i> Si le fil de l'interface utilisateur est occupé. Vous devez également séparer l'interface utilisateur du code de traitement de fichier. Il n'est pas nécessaire d'accéder à la forme principale comme celle-ci lorsque vous pouvez passer des lecteurs, etc. comme paramètres de la méthode