justinstenning / SharedMemory

C# shared memory classes for sharing data between processes (Array, Buffer and Circular Buffer)
https://www.nuget.org/packages/SharedMemory
Other
566 stars 118 forks source link

SharedMemory.BufferReadWrite truncating char array #57

Closed marekpraski closed 3 years ago

marekpraski commented 3 years ago

thank you for providing this library. When trying to use, however, I run into a serious problem. I want to use SharedMemory package to share data between two C# apps written in C# .Net 3.5 (unfortunately cannot upgrade). I wrote a simple test to see how it works

    private void runTest()
    {
        string testText = "someTest";   //"some", "someTest12"
        CreateOrOpenMappedFile(testText);
        string result = ReadMemoryMappedFile();
    }

    protected void CreateOrOpenMappedFile(string data)
    {
        char[] dataBuffer = data.ToCharArray();
        SharedMemory.BufferReadWrite buff = new SharedMemory.BufferReadWrite("sharedMemoryName", 4096);
        buff.Write(dataBuffer);
    }
    protected string ReadMemoryMappedFile()
    {
        char[] data = new char[10];         
        SharedMemory.BufferReadWrite buff = new SharedMemory.BufferReadWrite("sharedMemoryName");
        buff.Read(data);
        buff.Close();
        return new string(data);
    }

In runTest method I expected testText string to be the same as result, but what I was getting was a string that was clipped. For testText == "someTest" result was "some", for "some", result was "so", for "someTest12" it was "someT". What could be happening here? Marek

daxpandhi commented 3 years ago

Marek, I could be wrong but I think your buff object may be getting lost. If you declare it as a field and have both methods access that object, it might fix it.

marekpraski commented 3 years ago

daxpandhi, thanks but it did not work .... Anyhow, this is just an example to show the problem, in real life I would want the read and the write methods be in two separate projects (applications).

daxpandhi commented 3 years ago

I use it exactly like you want (although I rely on the circular buffer) in a production app. In any case, hopefully someone with more knowledge will be able to help you out.

justinstenning commented 3 years ago

@marekpraski I haven't had time to check fully why this is happening for you, however if you instead encode to bytes it works fine. My guess is that the size of a char is being incorrectly calculated as 1 byte instead of 2 bytes somewhere under the covers and therefore you only get half the data.

What @daxpandhi said is also valid, there is a small chance the GC will clean up the "owner" buff before you have read the value in this example. So definitely modify to maintain a reference to your shared buffers and dispose of them when you are ready to.

    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine(runTest());
        }

        private static string runTest()
        {
            string testText = "someTest";   //"some", "someTest12"
            CreateOrOpenMappedFile(testText);
            string result = ReadMemoryMappedFile();

            return result;
        }

        protected static void CreateOrOpenMappedFile(string data)
        {
            byte[] dataBuffer = Encoding.UTF8.GetBytes(data);
            SharedMemory.BufferReadWrite buff1 = new SharedMemory.BufferReadWrite("sharedMemoryName", 4096);
            buff1.Write(dataBuffer);
        }
        protected static string ReadMemoryMappedFile()
        {
            byte[] data = new byte[20];
            SharedMemory.BufferReadWrite buff2 = new SharedMemory.BufferReadWrite("sharedMemoryName");
            buff2.Read(data);
            buff2.Close();
            return Encoding.UTF8.GetString(data);
        }
    }
marekpraski commented 3 years ago

@spazzarama, it does work indeed when I convert to bytes as you suggested. Thank you