6
votes

Processus de processus simultanément tels qu'ils arrivent en C #

J'ai une application qui fonctionne bien pour le traitement de fichiers qui atterrissent dans un répertoire sur mon serveur. Le processus est le suivant:

1) check for files in a directory
2) queue a user work item to handle each file in the background
3) wait until all workers have completed
4) goto 1


3 commentaires

Qu'advient-il d'un fichier après sa traité? reste-t-il dans le même répertoire? Supprimé? déplacé? De plus, les fichiers sont-ils largués dans le répertoire serveur nommé systématiquement avec la même extension?


Je ne comprends pas comment votre processus comme indiqué ci-dessus empêche les fichiers d'être traité deux fois.


Une fois qu'un fichier est traité, il est supprimé à l'étape 2, c'est pourquoi, après la fin de l'étape 3, tous les fichiers du dossier devraient être traités et n'ont pas été traités précédemment.


4 Réponses :


6
votes

Je suggérerais de conserver une liste de fichiers que vous traitez actuellement. Demandez au fil de se retirer de cette liste lorsque le fil se termine. Lorsque vous recherchez de nouveaux fichiers, excluez ceux de la liste actuellement en cours.


3 commentaires

Comment gardez-vous une trace de laquelle les fichiers ont été traités après leur retrait de la file d'attente de fil?


Il a déjà ce problème, alors je suppose que cela est déjà résolu par, par exemple, le fichier étant supprimé à la fin du processus.


Oui, c'est essentiellement ce que je pensais - espérait simplement qu'il y avait un paradigme de producteur-consommateur existant qui est jugé et vrai plutôt que de rouler le mien. Merci.



3
votes

Déplacez les fichiers dans un répertoire de traitement avant de commencer les threads. Ensuite, vous pouvez tirer et oublier les threads et tout administrateur peut voir en un coup d'œil ce qui se passe.


1 commentaires

Cela suppose qu'il peut même faire cela sur le serveur, mais j'aime cette idée parce que vous savez quels fichiers qui doivent être / sont / ont été traités en vertu d'eux dans leurs répertoires respectifs.



3
votes

La frayer un fil par objet à traiter n'est presque jamais une bonne approche. Dans votre cas lorsque le nombre de fichiers ira au-dessus de plusieurs centaines d'un seul thread-par-fichier rendra la performance d'application plutôt mauvaise et avec un processus 32 bits commencera à court d'espace d'adresses.

La solution de liste de Falcon sombre est assez simple et correspond à votre algorithme. J'utiliserais réellement la file d'attente (Concurrentqueue - http://msdn.microsoft.com/ FR-US / Bibliothèque / DD267265.aspx ) Pour mettre des éléments à traiter d'un côté (c'est-à-dire sur la base des analyses périodiques de l'observateur de fichiers) et choisissez des éléments de traitement par un ou plusieurs threads de l'autre côté. Vous voulez généralement un nombre plus petit de threads (I.e. 1-2x Nombre de CPU pour la charge intensive de la CPU).

Envisagez également d'utiliser la bibliothèque parallèle de tâche (comme parallèle.foreach - http: // msdn.microsoft.com/en-us/library/dd989744.aspx ) Pour faire face à plusieurs threads.

Pour minimiser le nombre de fichiers à gérer, je garderais une liste des éléments qui sont déjà traités - chemin de fichier + Date de dernière modification (sauf si vous pouvez obtenir ces informations à partir d'autres sources).


0 commentaires

1
votes

Mes deux questions principales seraient:

  1. Quelle est la taille des fichiers?
  2. Combien de fois les fichiers vont-ils apparaître?

    Selon votre réponse, je pourrais aller avec l'algorithme de consommateur de producteur suivant:

    1. Utilisez un observateur de système de fichiers pour voir qu'il existe une activité dans le répertoire que vous surveillez
    2. Lorsque l'activité se produit, commencez à interroger "légèrement"; qui est tester chaque fichier disponible pour voir s'il n'est pas verrouillé (c'est-à-dire, essayez d'ouvrir des privilèges d'écriture ouverts à l'aide d'une méthode d'extension islocked simple qui teste via un try); Si 1 ou plusieurs fichiers ne sont pas libres, définissez une minuterie pour s'éteindre dans une durée (plus longue si vous attendez moins de fichiers, plus courtes si plus petits et / ou plus fréquents) pour tester à nouveau les fichiers
    3. Dès que vous voyez qu'un fichier est libre, traitez-le (c'est-à-dire le déplacer dans un autre dossier, mettez un élément dans une file d'attente simultanée, demandez à votre filetage de votre consommateur la file d'attente, archivez les fichiers / résultats).
    4. a une sorte de mécanisme de persistance comme Alexei mention (c'est-à-dire le disque / la base de données) pour pouvoir récupérer votre traitement où vous vous êtes laissé en cas de défaillance du système.

      Je pense que c'est une bonne combinaison de comportement non bloquant et faible d'utilisation de la CPU. Mais mesurez vos résultats avant et après. Je vous recommanderais d'utiliser le threadpool et essayez de garder les threads de blocage (c'est-à-dire essayer d'assurer la réutilisation du fil en ne faisant pas blocage en faisant quelque chose comme thread.sleep)

      Notes:

      1. base Le nombre de filets de traitement des fichiers sur le nombre de processeurs et de cœurs disponibles sur la machine; considérez également la charge du serveur
      2. FileSystemWatcher peut être finiky; Assurez-vous qu'il fonctionne de la même machine que vous surveillez (c'est-à-dire, sans regarder un serveur distant), sinon vous devrez réinitialiser la connectivité de temps en temps.
      3. Je n'aurais certainement pas abonnée un processus différent par fichier; Les threads multiples doivent être suffisants suffisants; La réutilisation des threads est la meilleure. Les procédés de frai sont une opération très coûteuse et les fils de frai sont une opération coûteuse. Alexei a une bonne information sur la bibliothèque parallèle de la tâche WRT; Il utilise le threadpool.

0 commentaires