2010-07-07 5 views
3

J'essaye d'écrire à différentes pièces d'un gros fichier en utilisant plusieurs threads, juste comme un téléchargeur de fichier segmenté ferait.Écriture multithread de fichier

Ma question est, quelle est la façon sécuritaire de faire cela? Dois-je ouvrir le fichier en écriture, créer mes threads, en passant l'objet Stream à chaque thread? Je ne veux pas qu'une erreur se produise car plusieurs threads accèdent au même objet potentiellement au même moment.

C'est du C# au fait.

Répondre

14

je suggère personnellement que vous allez chercher les données dans plusieurs threads, mais en fait écrire à partir d'un seul fil. C'est probablement beaucoup plus simple de cette façon. Vous pourriez utiliser une file d'attente producteur/consommateur (qui est vraiment facile dans .NET 4) et ensuite chaque producteur nourrirait des paires d '"index, données". Si le thread de consommation pouvait alors rechercher, écrire, rechercher, écrire, etc., séquentiellement

+0

Seul problème est, un fichier peut être énorme, un gigaoctet même long. Cela ne consomme-t-il pas beaucoup de mémoire pour le stocker en mémoire et le passer à un seul thread? – Icemanind

+1

Lire la réponse de Jon à nouveau. Il ne suggère pas de stocker tout le fichier en mémoire en une fois. –

+0

Oui, désolé. J'ai posté mon commentaire avant de l'éditer. – Icemanind

1

S'il s'agissait d'une programmation Linux, je vous recommande de regarder dans la commande pwrite(), qui écrit un tampon dans un fichier à un décalage donné. Une recherche rapide de la documentation C# ne révèle cependant rien de tel. Est-ce que quelqu'un sait si une fonction similaire existe?

+0

Vous chercheriez simplement une section donnée d'un flux avant d'écrire. L'utilisation de la propriété Position sur Stream serait le moyen le plus simple de le faire. –

+0

Une autre approche de Unix-land serait mmap() le fichier et effectuer les écritures aux emplacements corrects en mémoire. Mais les fichiers de plus de ~ 2,5 Go seraient très difficiles à gérer sur les systèmes 32 bits. (Le noyau sauverait simplement des données en cours de route, donc même les systèmes à petite mémoire pourraient le faire - la limite vient de la petite quantité de mémoire virtuelle.) – sarnold

+0

@Jon: Cela vous forcerait à synchroniser toutes vos écritures pour éviter une condition de concurrence sur la position du flux de fichiers (ce qui va à l'encontre du but d'avoir plusieurs rédacteurs). Supposons que deux threads modifient 'Position', puis les deux écrivent des données. Une ou les deux écrit ira au mauvais endroit. L'astuce (que 'pwrite()' permet) est d'ignorer complètement la position du flux. – Karmastan

1

Bien que l'on puisse être capable d'ouvrir plusieurs flux pointant vers le même fichier, et d'utiliser un flux différent dans chaque thread, je conseillerais d'utiliser un seul thread pour l'écriture sans aucune raison de faire autrement. Même si deux ou plusieurs threads peuvent écrire simultanément dans le même fichier, cela ne veut pas dire que c'est une bonne idée. Il peut être utile que le thread unifié tente de séquencer les écritures dans un ordre raisonnable pour éviter de nombreuses recherches aléatoires; les avantages en termes de performances dépendent de l'efficacité avec laquelle le système d'exploitation peut mettre en cache et planifier des écritures aléatoires. Ne devenez pas fou en optimisant de telles choses s'il s'avère que le système d'exploitation fait du bon travail, mais soyez prêt à ajouter une certaine optimisation si le comportement par défaut du système d'exploitation s'avère être médiocre.