Comment traiter les éléments en file d'attente en série sur un fil de faible priorité à l'aide des extensions parallèles

StackOverflow https://stackoverflow.com/questions/4252634

Question

Je veux savoir quelle est la meilleure façon de traiter les résultats d'un processus de longue durée en série mais sur un fil à faible priorité en utilisant le . NET 4.0 extensions parallèles .

J'ai la classe suivante que les deux font l'exécution et fournit les résultats:

public class Step 
{
  public string Name { get; set; }
  public TimeSpan Duration { get; set; }
  public bool Completed { get; set; }

  public void Execute() 
  {
     DateTime before = DateTime.Now;
     RemotedService.DoSomeStuff();
     Duration = DateTime.Now - before;
     Completed = true;
  }
}

Comment puis-je traiter ces étapes et aussi les enregistrer dans un fichier, dans l'ordre, après leur traitement? Je voudrais les enregistrer dans un fichier en RemotedService.DoSomeStuff() attend une réponse du serveur.

L'écriture dans le fichier serait comme ceci:

using (StreamWriter w = File.AppendText("myFile.txt"))
{
  var completedStep = completedSteps.Dequeue();
  w.WriteLine(string.Format("Completed {0} with result: {1} and duration {2}", 
                            completedStep.Name, 
                            completedStep.Completed, 
                            completedStep.Duration));
}

Une option qui vient à l'esprit est de les ajouter à une Queue et un Timer que les processus eux. Mais cela ne profite pas de temps d'arrêt des appels déportées.

Une autre option qui vient à l'esprit est d'écrire chaque résultat de manière asynchrone au fichier en utilisant un System.Threading.Tasks.Task par Step, mais cela ne garantit pas qu'ils seront sauvés en ordre et peuvent également introduire discorde avec l'écriture du fichier.

Était-ce utile?

La solution

Je suggère la création d'un BlockingCollection<Step> (voir l'espace de noms de System.Collections.Concurrent). Chaque étape est terminée, il est ajouté à cette collection. Le comportement par défaut de BlockingCollection est de fonctionner comme une file d'attente, de sorte que vous obtiendrez le comportement FIFO vous cherchez.

Un second services de fil de la file d'attente, suppression de chaque élément et l'écriture dans un fichier journal.

Donc, si vous avez ajouté la file d'attente:

static private BlockingCollection<Step> LogQueue = new BlockingCollection<Step>();

Vous serait ajouter à votre méthode de Execute, après que l'élément est terminé:

LogQueue.Add(this);

Et votre fil d'enregistrement, que vous commencez dans le constructeur statique:

static void LoggingThread()
{
    using (var w = new StreamWriter(...))
    {
        while (!LogQueue.IsCompleted())
        {
            Step item;
            if (LogQueue.TryTake(out item))
            {
                w.WriteLine(....);
            }
        }
    }
}

Le fil de l'exploitation forestière comme je l'ai écrit il utilise un fil de System.Threading. Il pourrait y avoir un moyen plus facile ou meilleure façon de le faire avec TPL. Je ne suis pas encore terriblement familier avec TPL, donc je ne pouvais pas dire.

Autres conseils

Une approche est de créer une coutume Planificateur de tâches (voir http: // msdn .microsoft.com / fr-fr / bibliothèque / ee789351.aspx ). Votre planificateur de tâches personnalisé peut limiter à un accès simultané à-un-temps et de faire respecter l'exécution stricte dans l'ordre.

Création d'un planificateur de tâches vous permet également de contrôler la priorité du fil, ou ApartmentState qui peut être souhaitable dans certaines situations.

Vous décrivez littéralement le cas d'utilisation pour Workflow Foundation - il fait tout ce genre de choses pour vous:)

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top