2008-09-17 4 views
1

Je travaille sur un projet avec des exigences de performance de peek, nous avons donc besoin de regrouper plusieurs opérations (par exemple persister les données dans une base de données) pour plus d'efficacité.Connaissez-vous une bibliothèque Bulked/Batched Flows pour C#

Cependant, je veux notre code pour maintenir un flux facile à comprendre, comme:

input = Read(); 
parsed = Parse(input); 
if (parsed.Count > 10) 
{ 
    status = Persist(parsed); 
    ReportSuccess(status); 
    return; 
} 
ReportFailure(); 

La fonction que je cherche ici est automatiquement ont persist() se produire dans vracs (et ergo de manière asynchrone), mais se comporte comme s'il était synchrone (l'utilisateur devrait bloquer jusqu'à ce que l'action en bloc soit terminée). Je veux que l'implémenteur soit capable d'implémenter Persist (ICollection). Je me suis penché sur la programmation par flux, avec laquelle je ne suis pas très familier. J'ai vu une bibliothèque pour fbp en C# here, et j'ai joué un peu avec Microsoft Workflow Foundation, mais j'ai l'impression que les deux sont trop exigeants pour ce dont j'ai besoin. Que utiliseriez-vous pour mettre en œuvre un comportement de flux gonflé? Notez que je voudrais obtenir un code qui est exactement comme ce que j'ai écrit (simple à comprendre & debug), donc les solutions qui impliquent le rendement ou la configuration afin de connecter les flux les uns aux autres sont inadéquates pour mon but. Aussi, chaining n'est pas ce que je cherche - je ne veux pas d'abord construire une chaîne et ensuite l'exécuter, je veux un code qui ressemble à un simple flux ("Do A, Do B, si C alors faites D ").

Répondre

0

Je ne sais pas si c'est ce dont vous avez besoin, car il est basé sur sqlserver, mais avez-vous essayé de jeter un oeil à SSIS et ou DTS?

+0

Pas vraiment. Supposons que j'ai quelques fonctionnalités de base de PersistBulk() qui accepte une grande quantité d'éléments et les persiste (indépendamment de l'implémentation de bas niveau). Je veux exposer une méthode PersistSingleItem() synchrone. Votre réponse n'est pas vraiment pertinente, merci. – ripper234

1

Problème courant - Au lieu d'appeler Persist, je charge habituellement les commandes (ou smt le long de ces lignes) dans une classe Persistor puis, une fois la boucle terminée, j'appelle Persistor.Persist pour persister le batch. Quelques points seulement - Si vous générez sql, les commandes que vous ajoutez à la persistance peuvent représenter vos requêtes d'une manière ou d'une autre (avec des objets intégrés, des objets personnalisés ou simplement des chaînes de requête). Si vous appelez des procédures stockées, vous pouvez utiliser les commandes pour ajouter des éléments à un élément XML qui sera transmis au SP lorsque vous appelez la méthode persist.

espère que cela aide - Assez sûr qu'il ya un motif pour cela, mais dunno le nom :)

0

Une chose simple que vous pouvez faire est de créer un MemoryBuffer où vous appuyez sur les messages qui les ajouter simplement à une liste et résultats. Ce MemoryBuffer a un System.Timers.Timer qui est invoqué périodiquement et effectue les mises à jour "réelles". Une telle implémentation peut être trouvée dans un serveur Syslog (C#) à http://www.fantail.net.nz/wordpress/?p=5 dans lequel les messages syslog sont journalisés à un serveur SQL périodiquement dans un lot.

Cette approche peut ne pas être bonne si les informations envoyées à la base de données sont importantes, car si quelque chose ne va pas, vous perdrez les messages dans MemoryBuffer.

0

Comment utiliser la classe BackgroundWorker pour conserver chaque élément de manière asynchrone sur un thread séparé? Par exemple:

using System; 
using System.Collections; 
using System.Collections.Generic; 
using System.ComponentModel; 
using System.Threading; 

class PersistenceManager 
{ 
    public void Persist(ICollection persistable) 
    { 
     // initialize a list of background workers 
     var backgroundWorkers = new List<BackgroundWorker>(); 

     // launch each persistable item in a background worker on a separate thread 
     foreach (var persistableItem in persistable) 
     { 
     var worker = new BackgroundWorker(); 
     worker.DoWork += new DoWorkEventHandler(worker_DoWork); 
     backgroundWorkers.Add(worker); 
     worker.RunWorkerAsync(persistableItem); 
     } 

     // wait for all the workers to finish 
     while (true) 
     { 
     // sleep a little bit to give the workers a chance to finish 
     Thread.Sleep(100); 

     // continue looping until all workers are done processing 
     if (backgroundWorkers.Exists(w => w.IsBusy)) continue; 

     break; 
     } 

     // dispose all the workers 
     foreach (var w in backgroundWorkers) w.Dispose(); 
    } 

    void worker_DoWork(object sender, DoWorkEventArgs e) 
    { 
     var persistableItem = e.Argument; 
     // TODO: add logic here to save the persistableItem to the database 
    } 
} 
+1

Vous n'avez pas besoin de sauvegarder chaque "worker" dans backgroundWorkers? – beach

+0

Oups! Oui bien sûr. Désolé, j'ai raté ça. Cette ligne de code était dans ma tête, mais ne l'a jamais fait dans le post. Je vais le réparer maintenant. Bonne prise, merci. – Robin

Questions connexes