2010-08-17 13 views
31

Aquí está mi situación. Me gustaría hacer que escribir en el sistema de archivos sea lo más eficiente posible en mi aplicación. La aplicación tiene varios subprocesos y cada subproceso posiblemente puede escribir en el mismo archivo. ¿Hay alguna forma de que pueda escribir en el archivo de forma asincrónica desde cada hilo sin tener las escrituras en los diferentes hilos juntos, por así decirlo?Escribir en un archivo de varios subprocesos de forma asincrónica C#

Estoy usando C# y .NET 3.5, y también tengo las extensiones reactivas instaladas.

Respuesta

11

Eche un vistazo a Asynchronous I/O. Esto liberará la CPU para continuar con otras tareas.
combinan con ReaderWriterLock como @Jack B ágil mencionó

Si por

escritura al sistema de archivos como eficiente posible

que significa hacer el archivo real de E/S lo más rápido posible Te va a costar mucho acelerarlo, el disco es físicamente más lento. ¿Tal vez SSD?

+2

Esto no parece abordar la cuestión, el tema "golpea juntos". –

+0

Sí, ¿cómo evitar que las escrituras asincrónicas colisionen? –

+2

De la misma manera que maneja cualquier contención de recursos en un sistema de subprocesos múltiples. Cabellos. ReadWriterLock (o ReaderWriterLockSlim con 4.0/Parallel Extensions + 3.5) permite que se realicen varias lecturas al mismo tiempo, por lo que si eso es algo que desea, úselo. –

7

Lo que haría es tener hilos de trabajo separados dedicados a la tarea de escribir archivos. Cuando uno de sus otros hilos necesita escribir algunos datos, debe llamar a una función para agregar los datos a un ArrayList (o algún otro contenedor/clase). Dentro de esta función, debe haber una instrucción de bloqueo en la parte superior para evitar que se ejecute más de un hilo simultáneamente. Después de agregar la referencia a ArrayList, regresa y continúa con sus tareas. Hay un par de maneras de manejar los hilos de escritura. Probablemente lo más simple es simplemente ponerlo en un bucle infinito con una declaración de suspensión al final para que no mastique su CPU (s). Otra forma es usar primitivas de subprocesos y pasar a un estado de espera cuando no haya más datos para escribir. Este método implica que debe activar el hilo con algo así como el método ManualResetEvent.Set.

Hay muchas maneras diferentes de leer y escribir archivos en .NET. He escrito un programa de referencia y dar los resultados en mi blog:

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

Yo recomendaría el uso de los métodos ReadFile y WriteFile de Windows si necesita rendimiento. Evite cualquiera de los métodos asincrónicos, ya que mis resultados de referencia muestran que obtiene un mejor rendimiento con métodos de E/S síncronas.

Bob Bryan CMDS

5

Mientras cerraduras basadas hilo puede solucionar esto, hay una manera que funciona a través de hilos, pero es probablemente el más utilizado cuando tiene varios procesos de escritura hasta el final de un solo archivo.

Para obtener este comportamiento en los procesos (o subprocesos también), especifique que desea escribir anexos atómicos en el sistema operativo cuando se crean los identificadores de archivos del sistema operativo. Esto se hace especificando O_APPEND en Posix (Linux, Unix) y FILE_APPEND_DATA en Windows.

En C# no llama directamente al sistema operativo 'abierto', o 'Crear archivo' directamente al sistema, pero hay formas de obtener este resultado.

me preguntó cómo hacer esto en Windows hace un tiempo, y tiene dos buenas respuestas aquí: How can I do an atomic write/append in C#, or how do I get files opened with the FILE_APPEND_DATA flag?

Básicamente, se puede utilizar FileStream() o PInvoke, sugeriría FileStream() sobre PInvoke por razones obvias .

Puede usar argumentos de constructor para FileStream() para especificar E/S de archivo asíncrono además del indicador FileSystemRights.AppendData, que le debe proporcionar tanto E/S asíncrona como anotaciones de adición atómica a un archivo.

Advertencia: Algunos sistemas operativos tienen límites en el número máximo de bytes que pueden escribirse atómicamente de esta manera, y exceder ese umbral eliminará la promesa de atomicidad del sistema operativo.

Debido a este último problema, recomendaría seguir con la administración de contención de estilo lock() al tratar de resolver su problema en un solo proceso.

3

Para aquellos que prefieren código, estoy usando siguiente de hacer el registro remoto de aplicaciones web ...

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(); 
     } 
    } 
} 

Hope esto le ahorra un tiempo

+0

¡Muy bien! Falta algo de la firma del método si intentas hacer de esto un método de extensión de Strings. Prefijo "texto de cuerda" con "este texto de cuerda" para el primer parámetro. –

+0

@JasonFoglia Hola Jason, hecho. –

+0

La pregunta especificada * asincrónicamente *. Esto es todo sincrónico. – Servy

Cuestiones relacionadas