2010-08-17 12 views
31

İşte durumum. Uygulamamda dosya sistemine mümkün olduğunca verimli yazmayı isterim. Uygulama çok iş parçacıklı ve her iş parçacığı aynı dosyaya yazabilir. Dosyaya farklı iş parçacığı başlıklarında birlikte yazmadan, her iş parçacığından eşzamansız olarak yazabileceğim bir yol var mı?Birden çok iş parçacığının eşzamansız olarak bir dosyaya yazmak C#

C# ve .NET 3.5 kullanıyorum ve Reaktif Uzantıları da yüklü.

cevap

11

Asynchronous I/O'a bakın. Bu, diğer görevlere devam etmek için cpu serbest bırakacaktır.

tarafından verimli olabildiğince gerçek dosyayı ben bulunmak anlamına

/Ç mümkün olduğunca hızlı gibi dosya sistemine yazma Eğer @Jack B Çevik

belirtildiği gibi
ReaderWriterLock ile birleştirin Bunu hızlandırmak için zor bir zamanınız olacak, disk sadece fiziksel olarak daha yavaş. Belki SSD? Dosya akışına erişmek için Reader/Writer kilitlerini kullanın.

+2

kaydeder kod tercih edenler için –

+0

Evet, eşzamansız yazmaların çarpışmasını nasıl önler? –

+2

Çok iş parçacıklı bir sistemde herhangi bir kaynak çekişme ile aynı şekilde. Kilitler. ReadWriterLock (veya 4.0/Parallel Extensions + 3.5 ile ReaderWriterLockSlim), birden fazla okunmanın eşzamanlı olarak gerçekleşmesine izin verir, böylece istediğiniz bir şey varsa, onu kullanın. –

3

Dosya akışına erişmek için Reader/Writer kilitlerini kullanın. Ben ne yapardım

7

dosyaları yazma görevi adanmış ayrı çalışan iş parçacığı (ler) var olduğunu. Diğer iş parçacıklarınızdan birisinin veri yazması gerektiğinde, verileri ArrayList'e (veya başka bir kapsayıcıya/sınıfa) eklemek için bir işlev çağırmalıdır. Bu işlevin içinde, aynı anda birden fazla iş parçacığının yürütülmesini engellemek için üstte bir kilit ifadesi bulunmalıdır. ArrayList'e referans ekledikten sonra geri döner ve işleri ile devam eder. Yazma iş parçacığı (ları) işlemek için birkaç yol vardır. Muhtemelen en basit olanı, sonunda bir uyku ifadesiyle sonsuz bir döngüye sokmaktır, böylece cpu (larınızı) çiğnemez. Başka bir yol, iş parçacığı ilkellerini kullanmak ve yazılacak daha fazla veri olmadığında bekleme durumuna geçmektir. Bu yöntem, iş parçacığı ManualResetEvent.Set yöntemi gibi bir şeyle etkinleştirmeniz gerektiğini gösterir.

okumak ve .NET dosyaları yazmak için birçok farklı yolu vardır. Bir kıyaslama programı yazılı ve benim blog sonuçları verir adres:

http://designingefficientsoftware.wordpress.com/2011/03/03/efficient-file-io-from-csharp

Sana performansı gerekirse, Windows ReadFile ve WriteFile yöntemlerle öneriyoruz. Karşılaştırma sonuçlarım, senkronize G/Ç yöntemleri ile daha iyi performans gösterdiğinizi gösterdiğinden, asenkronize yöntemlerden herhangi birini kullanmayın.

Bob Bryan MCSD

5

iplik bazlı kilitler bunu çözmek mümkün olmakla birlikte, parçacığı üzerinde çalışan bir tutum yoktur, ancak tek bir dosya sonuna yazma birden çok işlem olduğunda muhtemelen en iyi kullanılır.

OS dosya tanıtıcısı oluşturulduğunda atomik ekleme işletim sistemine yazıyor istediğinizi belirtin (çok ya da parçacığı) süreçler boyunca bu davranışı almak için. Bu, Windows altında Posix (Linux, Unix) ve FILE_APPEND_DATA altında O_APPEND belirtilerek yapılır. Eğer OS 'açık' veya 'CreateFile' sistemini demiyorlar C#

doğrudan çağırır, ancak bu sonucu elde etmek için yollar vardır.

Bir süre önce Windows altında bunun nasıl istedi ve burada iki iyi cevap var: Temelde How can I do an atomic write/append in C#, or how do I get files opened with the FILE_APPEND_DATA flag?

, sen FileStream() veya Pınvoke kullanabilirsiniz, ben bilinen nedenlerle PInvoke üzerinde FileStream() öneririm .

Yapıcı argümanlarını FileSystemRights.AppendData bayrağına ek olarak eşzamansız dosya G/Ç'sini belirtmek için FileStream() öğesine kullanabilirsiniz; bu, hem async I/O hem de atomik ek yazımları bir dosyaya vermelidir.

Uyarı: Bazı OS'lerin, bu şekilde atomik olarak yazılabilen maksimum bayt sayısı sınırlıdır ve bu eşiği aşmak, OS'nin atomiklik vaadini ortadan kaldıracaktır.

Bu son sonuçtan dolayı, sorununuzu tek bir işlem içinde ele almaya çalışırken lock() stili çekişme yönetimi ile kalmanızı öneririz. Bu işlem size zaman bu soruyu ele almak görünmüyor

3

, ben web uygulamalarının uzaktan günlüğü yapmak aşağıdakileri kullanıyorum ...

public static class LoggingExtensions 
{ 
    static ReaderWriterLock locker = new ReaderWriterLock(); 
    public static void WriteDebug(this string text) 
    { 
     try 
     { 
      locker.AcquireWriterLock(int.MaxValue); //You might wanna change timeout value 
      System.IO.File.AppendAllLines(Path.Combine(Path.GetDirectoryName(System.Reflection.Assembly.GetExecutingAssembly().GetName().CodeBase).Replace("file:\\", ""), "debug.txt"), new[] { text }); 
     } 
     finally 
     { 
      locker.ReleaseWriterLock(); 
     } 
    } 
} 

Umut, "bang head together" sorunu.

+0

Çok güzel! Strings'in bir uzantı yöntemini yapmaya çalışıyorsanız, yöntem imzasından bir şey eksik. İlk parametre için "bu metin" ile "string text" yazdım. –

+0

@JasonFoglia Merhaba Jason, bitti. –

+0

Belirtilen soru * senkronize olmayan *. Hepsi senkron. – Servy

İlgili konular