2013-08-20 6 views
1

J'ai un (documentation) que j'utilise là où le MatchEvaluator doit faire un peu de levage plutôt lourd. Les appels sont en cours vers une autre bibliothèque en utilisant la redirection StandardInput et StandardOutput. La nature de la bibliothèque est telle que je dois ouvrir un StandardInput puis le fermer pour obtenir les données que je veux en sortir via StandardOutput. Inutile de dire que c'est un processus plutôt intensif.Regex MatchEvaluator en parallèle

Cependant, j'ai plus de threads sur mon système et je me demandais s'il y avait un moyen d'exécuter le Regex avec le parallélisme. Je ne peux pas trouver de surcharge qui permette cela et je ne peux pas sembler trop conceptualiser même comment cela fonctionnerait étant donné la nature de Regex. J'ai pensé à briser artificiellement la chaîne, mais je crains que cela n'entraîne une rupture à un endroit qui entraîne un changement dans le traitement du Regex, car il utilise un look-around (mais pas beaucoup). Est-ce que quelqu'un peut faire la lumière sur la façon dont je pourrais être en mesure de paralléliser cela? C'est un document unique très volumineux avec plusieurs (centaines) de correspondances qui doivent être remplacées. Le résultat est un document unique avec toutes les chaînes correspondantes remplacées par la sortie de la fonction MatchEvaluator.

Exemple de document:

Random characters from all over the alphabet that have no use to me in this context. Including =, &, ", ', &, etc. [StringToReplace] More stuff I can ignore. [OtherStringToReplace]. More characters including foreign languages. 

J'utilise les éléments suivants Regex:

resultText = Regex.Replace(text, "(?<=\])[^\[\]]+(?=\[)", matchEval) 
+0

Vous pouvez placer tout votre motif entre parenthèses et utiliser 'Split '. Les résultats capturés seront renvoyés dans le tableau résultant (entre les parties divisées). Vous pouvez ensuite identifier les parties correspondantes par un simple comptage et traiter ces parties en parallèle, je suppose. –

+0

Votre modèle actuel serait utile ici, pour voir s'il peut être adapté à une telle solution. –

+0

Mais comment pourrais-je rejoindre les ensembles de résultats? (Pourquoi ne pas poster votre solution comme une réponse, pour que nous puissions y discuter?) – cjbarth

Répondre

3

Supposons que je veux mots de cette entrée et faire une opération coûteuse sur chacun d'eux comme conversion en majuscules :)

string input = @"abc 123 def 456 ghi 789 jkl mno pqr"; 
string pattern = @"[a-z]+"; 

Ce que je voudrais faire est:

1- Obtenez tous les matchs

var matches = Regex.Matches(input,pattern).Cast<Match>().Select(m=>m.Value); 

2- Est-ce que l'opération coûteuse sur tous les matches (parallèle) et stocker le résultat dans un dictionnaire

var dict = new ConcurrentDictionary<string, string>(); 
Parallel.ForEach(matches, m => 
{ 
    Thread.Sleep(1000); // <--Time consuming OP. 
    dict[m] = m.ToUpper(); 
}); 

3- Faire le remplacement en utilisant le dictionnaire

var output = Regex.Replace(input, pattern, m => dict[m.Value]); 
+0

+1 Vérifiez d'abord dict [m] pour éviter l'opération coûteuse. Avec un producteur, le modèle de consommation pourrait éviter un second .Replace. Le PO n'est pas réactif donc je ne suis pas enclin à tester. – Paparazzi

+1

Comme, dans une exécution donnée de l'application, le calcul de remplacement ne changera pas, l'utilisation d'un ConcurrentDictionary accélère vraiment les choses. C'était un modèle très facile à mettre en œuvre. Merci! – cjbarth