0

I got stuck in solving a problem in my current project. I'm coding a simulation in WPF/C# and included a Unity-Application in the window using the window-handles/hwnd pretty much like "Programmer" did in this answer. He also suggested namedpipes for the communication.

But the communication just works in one way - The server (WPF-App) is able to send messages to the client (the embedded Unity-App). If I try it the other way around, the whole Unity-App hungs up and stops working. As far as I was able to figure it out, as soon as I flush the writer or add the AutoFlush and then write something Unity gets stuck.

It is interesting, that the InBufferSize of the server is 0. Might this be the Problem?

This is my C#-Script in Unity assigned to a GameObject:

public class pipeCommunicationScript : MonoBehaviour
{
    NamedPipeClientStream client;

    public GameObject console;
    static Text consoleText;

    StreamReader reader;
    StreamWriter writer;

    int counter = 0;


    static bool _threadRunning;
    Thread _thread;

    void Start()
    {
        consoleText = console.GetComponent<Text>();
        consoleText.text = "trying to set up client";

        _thread = new Thread(StartClient);
        _thread.Start();
    }

    void StartClient()
    {
        _threadRunning = true;

        //Client
        consoleText.text = "Attempting to connect to pipe...";
        client = new NamedPipeClientStream(".","UnitySimulationPipe", PipeDirection.InOut);
        if (!client.IsConnected) { client.Connect(); }
        consoleText.text = "Connected to pipe.";

        writer = new StreamWriter(client);
        reader = new StreamReader(client);
        writer.AutoFlush = true;

        InvokeRepeating("sendThroughPipe", 5.5f, 5.5f);

        while (_threadRunning)
        {
            consoleText.text = "IN:" + reader.ReadLine();
        }

        _threadRunning = false;
    }


    void sendThroughPipe()
    {
        try
        {
            client.WaitForPipeDrain();
            writer.WriteLine("test" + counter);
        }
        catch(Exception e)
        {
            consoleText.text = "Exception while sending: " + e;
        }
        consoleText.text = "OUT: test" + counter;
        counter++;
    }


    void OnDisable()
    {
        if (_threadRunning)
        {
            _threadRunning = false;
       _thread.Join();
        }
    }
}

And this my Server-Script:

void StartServer()
{
    Task.Factory.StartNew(() =>
    {
        Console.WriteLine("Connection initialisation started");
        var server = new NamedPipeServerStream("UnitySimulationPipe", PipeDirection.InOut);
        server.WaitForConnection();

        while (!server.IsConnected)
        {
            Console.WriteLine("Connection not initialized");
            server.WaitForConnection();
        }

        Console.WriteLine("Connection initialized");


        reader = new StreamReader(server);
        writer = new StreamWriter(server);
        writer.AutoFlush = true;

        writer.WriteLine("startConnection");
        printOnStatusBar("OUT: startConnection");

        connected = true;


        Console.WriteLine("Current pipe readable: " + server.CanRead);

        Console.WriteLine("Pipe InBufferSize: " + server.InBufferSize);

        while (true)
        {
            Console.WriteLine("start while again");

            if (reader.Peek() > 0)
            {
                var l = reader.ReadLine();
                Console.WriteLine(reader.ReadLine());
                Console.WriteLine("read finished");
                server.WaitForPipeDrain();
            }
            Thread.Sleep(500);

        }
    });
}

2 Answers2

0

The most probable answer is, in fact, what you mentionned (bufferSize). You should check for the initialyzers parameters of every object you use. Don't worry, I'm sure you'll find the answer just by searching there. I used to create such code in the same way, it should work well.

0

Okay, I changed my initilisation of the server-object to (explanation of different parameters here):

var server = new NamedPipeServerStream("UnitySimulationPipe", PipeDirection.InOut, 1, 0, 0, 1024, 1024);

But I personally think, that this was just a minor mistake. The mainreason why my code didn't worked was, that I missed to call

server.WaitForPipeDrain();

after

writer.WriteLine("startConnection");
printOnStatusBar("OUT: startConnection");

in my server-code.