c# .net-4.0 memory-mapped-files

c# - MemoryMappedFile no funciona con 2 procesos?



.net-4.0 memory-mapped-files (2)

Estás luchando contra un detalle de implementación de BinaryWriter.Write (cadena). Primero escribe la longitud de la cadena, necesaria para que BinaryReader sepa cuántos caracteres necesita leer al leer la cadena. Para cadenas cortas, como "1", escribe un solo byte para almacenar la longitud.

Entonces el desplazamiento que pasas a CreateViewStream () es incorrecto, pasar 1 lo sobrescribirá en parte de la cadena escrita por el proceso A. El carácter sonriente que ves es el glifo de (char) 1. El byte de longitud de la cadena escrita por el proceso B.

Los archivos mapeados en memoria son problemáticos en el código administrado. Normalmente lees y escribes al declarar una estructura para configurar el diseño y el uso de punteros para acceder a la vista, pero eso requiere un código inseguro. Las corrientes son una abstracción bastante pobre para un pedazo de memoria, pero un mal necesario. También el motivo por el que los FMM tardaron tanto en estar disponibles en .NET.

Hice una prueba simple con un MemoryMappedFile como dice msdn :

2 procesos, 1 archivo mapeado de memoria:

  • el primer proceso agrega la cadena "1"
  • el primer proceso espera
  • el segundo proceso agrega la cadena "2" y termina
  • el primer proceso ahora lee todo el archivo mapeado de memoria

proceso A:

using (MemoryMappedFile mmf = MemoryMappedFile.CreateNew("testmap", 10000)) { bool mutexCreated; Mutex mutex = new Mutex(true, "testmapmutex", out mutexCreated); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8); writer.Write("1"); } mutex.ReleaseMutex(); Console.WriteLine("Start Process B and press ENTER to continue."); Console.ReadLine(); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream()) { BinaryReader reader = new BinaryReader(stream, Encoding.UTF8); Console.WriteLine("Process A says: {0}", reader.ReadString()); Console.WriteLine("Process B says: {0}", reader.ReadString()); } mutex.ReleaseMutex(); }

proceso B:

using (MemoryMappedFile mmf = MemoryMappedFile.OpenExisting("testmap")) { Mutex mutex = Mutex.OpenExisting("testmapmutex"); mutex.WaitOne(); using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0)) { BinaryWriter writer = new BinaryWriter(stream, Encoding.UTF8); writer.Write("2"); } mutex.ReleaseMutex(); }

El resultado es :

Hu?

¿Dónde está "1", "2"?

Sin embargo, si ejecuto SOLAMENTE el primer proceso (sin activar el proceso B) obtengo:

Qué me estoy perdiendo ?

Espero ver:

Process A says: 1 Process B says: 2


EDITAR

Noté una cosa aparentemente extraña en el código de ProcessB . Este código

using (MemoryMappedViewStream stream = mmf.CreateViewStream(1, 0))

crea una vista desde el primer byte, pero las cadenas en .NET tienen 2 bytes. Creo que debería ser suficiente para hacer que 1->2 convierta en 2. Entonces el desplazamiento de la vista ProcessB desde el inicio del archivo mapeado será después de la cadena "1" ya insertada de ProcessA .

En tu caso parece que los superpones .

Espero que esto ayude.