Voulez-vous utiliser Task Parallel Library avec les rapports d’avancement pour mettre à jour la firebase database

J’ai développé une application où plusieurs chaînes de connexion sont stockées. Je viens de parcourir pour la boucle et connectez chaque firebase database et exécutez SQL contre chaque firebase database. De cette façon, je mets à jour plusieurs bases de données avec une instruction SQL en bloc.

Maintenant, j’ai besoin d’utiliser maintenant Task Parallel Library pour mettre à jour plusieurs bases de données simultanément au lieu de mettre à jour un après un en boucle. Je veux aussi gérer l’exception et aussi montrer plusieurs barres de progression pour plusieurs opérations de firebase database. les fonctionnalités de pause et de reprise devraient être là.

Lorsque je clique sur le bouton, plusieurs connexions DB sont ouvertes et pour chaque tâche, une nouvelle barre de progression est ajoutée dans mon formulaire. chaque barre de progression indiquera la progression de chaque opération de firebase database. quand une tâche sera terminée, la barre de progression correspondante sera supprimée du formulaire.

n’importe qui peut me guider avec un exemple de code sur la façon de le faire avec TPL. Ici, j’ai un code qui met à jour une barre de progression, mais je dois mettre à jour plusieurs barres de progression. int itérations = 100;

ProgressBar pb = new ProgressBar(); pb.Maximum = iterations; pb.Dock = DockStyle.Fill; Controls.Add(pb); Task.Create(delegate { Parallel.For(0, iterations, i => { Thread.SpinWait(50000000); // do work here BeginInvoke((Action)delegate { pb.Value++; }); }); }); 

UPDATE Question

Je l’ai fait de cette façon. Le code fonctionne, mais toute la valeur de la barre de progression augmente séquentiellement J’ai un formulaire et un contrôle utilisateur dans les applications Winform. S’il vous plaît jeter un oeil à mon code et dites-moi ce qui ne va pas là-bas.

principal pour le code

 public partial class Main : Form { public Main() { InitializeComponent(); this.DoubleBuffered = true; } private void btnStart_Click(object sender, EventArgs e) { Progress ucProgress = null; Dictionary dicList = new Dictionary(); dicList.Add("GB", "conn1"); dicList.Add("US", "conn2"); dicList.Add("DE", "conn3"); fpPanel.Controls.Clear(); Task.Factory.StartNew(() => { foreach (KeyValuePair entry in dicList) { ucProgress = new Progress(); ucProgress.Country = entry.Key; ucProgress.DBConnection = entry.Value; fpPanel.BeginInvoke((MethodInvoker)delegate { fpPanel.Controls.Add(ucProgress); ucProgress.Process(); }); //fpPanel.Controls.Add(ucProgress); System.Threading.Thread.SpinWait(5000000); } }); } private void Main_Resize(object sender, EventArgs e) { this.Invalidate(); } private void Main_Paint(object sender, PaintEventArgs e) { using (LinearGradientBrush brush = new LinearGradientBrush(this.ClientRectangle, Color.WhiteSmoke, Color.LightGray, 90F)) { e.Graphics.FillRectangle(brush, this.ClientRectangle); } } } 

code de contrôle de l’utilisateur

 public partial class Progress : UserControl { public Progress() { InitializeComponent(); lblMsg.Text = ""; pbStatus.Minimum = 0; pbStatus.Maximum = 100; } public ssortingng Country { get; set; } public ssortingng DBConnection { get; set; } public ssortingng Sql { get; set; } public void SetMessage(ssortingng strMsg) { lblMsg.Text = strMsg; } public void Process() { var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); Task.Factory.StartNew(() => { lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "Connecting country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 30; }); System.Threading.Thread.SpinWait(50000000); //*********** lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "executing sql for country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 60; }); System.Threading.Thread.SpinWait(50000000); //*********** lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "sql executed successfully for country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 100; }); System.Threading.Thread.SpinWait(50000000); }); //System.Threading.Thread.SpinWait(50000000); // do work here } } 

peut-être que cela peut être un sharepoint départ. La gestion de la pause / reprise dépend de vos besoins et peut être modifiée.

 var cancellationTokenSource = new CancellationTokenSource(); var cancellation = cancellationTokenSource.Token; void UpdateDatabases(IEnumerable<...> databases, CancellationToken cancellation) { foreach(db in databases) { //create as many ProgressBar instances as databases you want to update //check if ProgressBar exist, then return it and reuse, otherwise create new ProgressBar pb = new ProgressBar(); pb.Maximum = iterations; pb.Dock = DockStyle.Fill; Controls.Add(pb); //start thread for every database/progress bar Task.Factory.StartNew(progressBar => { var start = (ProgressBar)progressBar).Value; //use last value in case of pause Parallel.For(start, iterations, new ParallelOptions(){CancellationToken = cancellation} (i, loopState) => { if (loopState.ShouldExitCurrentIteration) return; //perhaps check loopState.ShouldExitCurrentIteration inside worker method Thread.SpinWait(50000000); // do work here BeginInvoke((Action)delegate { ((ProgressBar)progressBar).Value++; }); }); }, pb, cancellation) .ContinueWith(task => { //to handle exceptions use task.Exception member var progressBar = (ProgressBar)task.AsyncState; if (!task.IsCancelled) { //hide progress bar here and reset pb.Value = 0 } }, TaskScheduler.FromCurrentSynchronizationContext() //update UI from UI thread ); } } //......... //Call UpdateDatabases(databases, cancellation) //To suspend, call cancellationTokenSource.Cancel(); //To resume - simply call UpdateDatabases again cancellationTokenSource = new CancellationTokenSource(); cancellation = cancellationTokenSource.Token; UpdateDatabases(databases, cancellation) 

Mettre à jour

J’ai revu ton code. Jetez un coup d’œil au code revisité et adaptez-le à vos besoins. Principales erreurs – gâchis avec les closures et la création du progrès à partir de thread non-ui. Pour activer le traitement en parallèle, vous pouvez utiliser Parallel.ForEach (voir MSND pour les éventuelles surcharges). De plus, la conception me semble un peu étrange (vous mélangez les données et la logique dans le Progress ). Du sharepoint vue de l’interface utilisateur, il est également étrange que les barres de progression apparaissent dans l’ordre de traitement mais pas dans l’ordre d’origine car elles sont dans la liste (le problème si vous décidez de sortinger la liste alphabétiquement)

J’espère que ça aide.

principal pour le code

  private void btnStart_Click(object sender, EventArgs e) { Progress ucProgress = null; Dictionary dicList = new Dictionary(); dicList.Add("GB", "conn1"); dicList.Add("US", "conn2"); dicList.Add("DE", "conn3"); fpPanel.Controls.Clear(); Func, object> createProgress = entry => { var tmp = new Progress {Country = entry.Key, DBConnection = entry.Value}; fpPanel.Controls.Add(tmp); return tmp; }; Task.Factory.StartNew(() => { //foreach (KeyValuePair entry in dicList) Parallel.ForEach(dicList, entry => { //create and add the Progress in UI thread var ucProgress = (Progress)fpPanel.Invoke(createProgress, entry); //execute ucProgress.Process(); in non-UI thread in parallel. //the .Process(); must update UI by using *Invoke ucProgress.Process(); System.Threading.Thread.SpinWait(5000000); }); }); } 

code de contrôle de l’utilisateur

 public void Process() { //uiScheduler - Not used //var uiScheduler = TaskScheduler.FromCurrentSynchronizationContext(); //The Task is not necessary because the Process() called from Parallel.ForEach //Task.Factory.StartNew(() => //{ //BeginInvoke or Invoke required lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "Connecting country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 30; }); System.Threading.Thread.SpinWait(50000000); //*********** lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "executing sql for country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 60; }); System.Threading.Thread.SpinWait(50000000); //*********** lblMsg.BeginInvoke((MethodInvoker)delegate { lblMsg.Text = "sql executed successfully for country " + Country; }); pbStatus.BeginInvoke((MethodInvoker)delegate { pbStatus.Value = 100; }); System.Threading.Thread.SpinWait(50000000); //}); //System.Threading.Thread.SpinWait(50000000); // do work here }