2017-06-08 1 views
1

Je suis novice en programmation C# et orientée objet en général. J'ai une application qui analyse les fichiers texte.C# - Délégués et BackgroundWorkers

Par défaut, le programme s'exécute sur le thread principal et l'application se bloque jusqu'à l'exécution.

I ont 5 méthodes vides qui prennent dans une liste de string comme paramètre.

Sur la base des différentes CheckBox les options, ces 5 méthodes vides sont exécutées dans des combinaisons.

Le BackgroundWorker effectue l'opération sur un fil différent. Ainsi, l'application ne gèle pas.

Cependant, je aurais besoin 15+ BackgroundWorkers pour chaque combinaison.

Ce qui suit est mon code:

public partial class Form1 : Form 
{ 
    List<string> textFiles = new List<string>(); 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    public void mParsing(List<string> textFiles) { /* parsing logic */ } 
    public void iParsing(List<string> textFiles) { /* parsing logic */ } 
    public void aParsing(List<string> textFiles) { /* parsing logic */ } 
    public void qParsing(List<string> textFiles) { /* parsing logic */ } 

    public void Summary() 
    { 
     // Logic to generate summary 
    } 

    private void btnGo_Click(object sender, EventArgs e) 
    { 
     if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false) 
     { 
      backgroundWorker1.RunWorkerAsync(); 
     } 
     else if (checkM.Checked == true && checkI.Checked == true && checkA.Checked == false && checkQ.Checked == false) 
     { 
      backgroundWorker2.RunWorkerAsync(); 
     }    

     //So On.... 
    } 

    private void backgroundWorker1_DoWork(object sender, DoWorkEventArgs e) 
    { 
     mParsing(textFiles); 
     Summary(); 
    } 
    private void backgroundWorker1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo); 
     if (dialogResult == DialogResult.Yes) 
     { 
      string summary = filepath; 
      Process.Start("notepad.exe", summary); 
     } 
    } 
    private void backgroundWorker2_DoWork(object sender, DoWorkEventArgs e) 
    { 
     mParsing(textFiles); 
     iParsing(textFiles); 
     Summary(); 
    } 
    private void backgroundWorker2_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) 
    { 
     DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo); 
     if (dialogResult == DialogResult.Yes) 
     { 
      string summary = filepath; 
      Process.Start("notepad.exe", summary); 
     } 
    } 
} 

Le Func<> n'accepte pas vide et datatype je suis un mauvais temps à comprendre les délégués et multi threading.

Mon problème est, je ne sais pas comment éviter plusieurs travailleurs de fond. Cela peut-il être mis en œuvre avec l'aide des délégués?

Mise à jour: .NET Framework Version: 4.0

+2

Utilisez-vous l'arrière-plan juste parce que c'est la première façon que vous avez découvert pour faire du multithreading et vous êtes bloqué avec? Ou pour une raison spécifique? Je demande parce que c'est un peu une façon obsolète de traiter le filetage. Et comme vous l'avez découvert, c'est trop complexe. – Jamiec

+0

@Jamiec, j'ai utilisé un fond d'écran parce que je l'ai utilisé dans le passé avec l'application VB.NET. Les méthodes mentionnées doivent être exécutées dans la séquence. Comment cela peut il etre accompli? En outre, une explication serait grandement appréciée. – Tango

+0

RunWorkerAsync() vous permet de passer un argument à DoWork. Clairement vous en aurez un bon usage ici, un BGW suffit. –

Répondre

1

réponse de Coolerfarmer fonctionne bien avec 4,5 .NET.

Cependant, en raison de .NET 4.0 limites, pour réaliser des exécutions Managed asynchrones avec l'aide de fils & délégués

Il ne peut pas être un moyen efficace d'effectuer l'exécution de combinaison de méthodes.

Ce que je l'ai été, a créé une méthode individuelle avec ordre d'exécution et utilisé le code suivant:

public partial class Form1 : Form 
{ 
    List<string> textFiles = new List<string>(); 

    public Form1() 
    { 
     InitializeComponent(); 
    } 

    public void mParsing(List<string> textFiles) { /* parsing logic */ } 
    public void iParsing(List<string> textFiles) { /* parsing logic */ } 
    public void aParsing(List<string> textFiles) { /* parsing logic */ } 
    public void qParsing(List<string> textFiles) { /* parsing logic */ } 

    public void Summary() 
    { 
     // Logic to generate summary 
    } 

    private void btnGo_Click(object sender, EventArgs e) 
    { 
     if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false) 
     { 
      Thread worker = new Thread(mOption); 
       if (!worker.IsAlive) 
       { 

        worker.Start(); 
        frm.Show(); // Displaying Form - Performing Operation.. Please Wait... 
        btn1.Enabled = false; 
       } 
     } 
     else if (checkM.Checked == true && checkI.Checked == true && checkA.Checked == false && checkQ.Checked == false) 
     { 
      Thread worker = new Thread(miOption); 
       if (!worker.IsAlive) 
       { 

        worker.Start(); 
        frm.Show(); // Displaying Form - Performing Operation.. Please Wait... 
        btn1.Enabled = false; 
       } 
     }    

     //So On.... 
    } 


     private void mOption() 
     { 
      mParsing(textFiles); 
      Summary(); 

      MethodInvoker inv = delegate 
      { 
       frm.Hide(); 

     DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo); 
     if (dialogResult == DialogResult.Yes) 
     { 
      string summary = filepath; 
      Process.Start("notepad.exe", summary); 
     } 
       this.btn1.Enabled = true; 

      }; 
      this.Invoke(inv); 
     } 

     private void miOption() 
     { 
      mParsing(textFiles); 
      iParsing(textFiles); 
      Summary(); 

      MethodInvoker inv = delegate 
      { 
       frm.Hide(); 

     DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo); 
     if (dialogResult == DialogResult.Yes) 
     { 
      string summary = filepath; 
      Process.Start("notepad.exe", summary); 
     } 
       this.btn1.Enabled = true; 

      }; 
      this.Invoke(inv); 
     } 

} 

Toutes les entrées avec des explications sont les bienvenues et merci à tous pour les entrées et suggestions.

1

En C# il y a async/Attendent qui est exactement ce dont vous avez besoin. Prenez cet exemple:

private async void btnGo_Click(object sender, EventArgs e) 
{ 
    if (checkM.Checked == true && checkI.Checked == false && checkA.Checked == false && checkQ.Checked == false) 
    { 
     await mParsing(textFiles); 
     DialogResult dialogResult = MessageBox.Show("View Summary?", MessageBoxButtons.YesNo); 
     if (dialogResult == DialogResult.Yes) 
     { 
      string summary = filepath; 
      Process.Start("notepad.exe", summary); 
     } 
    } 
} 

Pour que cela fonctionne les deux fonctions, btnGo_Click et mParsing doit avoir le async mot-clé dans sa définition. De plus, le type de retour de la fonction d'analyse doit être changé en Tâche.

public async Task mParsing(List<string> textFiles) 
{ 
    //Method containing parsing logic 
} 

De plus, vous avez besoin de quelques changements à votre fonction mParsing (maintenant asynchrone). E.g. blocage des appels comme new WebClient().DownloadString(url) doivent être remplacés par des appels non blocage new WebClient().DownloadStringTaskAsync(url)

Comme il n'y a pas toujours un appel non bloquant disponible, vous pouvez également utiliser Task.Run():

public async Task mParsing(List<string> textFiles) 
{ 
    await Task.Run(() => { 
     //Do blocking calls 
    }); 
} 
+0

Bonjour Coolerfarmer, Malheureusement, j'utilise .NET Framework 4. Je ne peux pas le changer pour le dernier. Comment cela peut-il être mis en œuvre sans async? – Tango