Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Based on the feedback, it seems my issue is that I risk blocking when two communicating programs both have their sending messages blocked. So I moved the sending function to a seperate class now.</p> <p>Following is the class I decided to use. It should be started up once ready for use, and can be called with a target TcpClient and a message, the call can be done either Blocking or Nonblocking (Nonblocking returns true is message is accepted)</p> <pre><code> public class TcpSender { Mutex moveToInternal = new Mutex(); Mutex startOnce = new Mutex(); List&lt;Message&gt; internalMessages = new List&lt;Message&gt;(); List&lt;Message&gt; externalMessages = new List&lt;Message&gt;(); Thread mainLoop; String status = "stopped"; //returns true if started. public Boolean Start() { if (startOnce.WaitOne(0)) { status = "started"; mainLoop = new Thread(new ThreadStart(InternalMainLoop)); mainLoop.IsBackground = true; mainLoop.Start(); return true; } return false; } private void InternalMainLoop() { while (status == "started") { Boolean didSomething = false; //pickup new messages and move to internal buffer if (externalMessages.Count &gt; 0) { didSomething = true; if (moveToInternal.WaitOne()) { internalMessages.AddRange(externalMessages); externalMessages.Clear(); moveToInternal.ReleaseMutex(); } } //deliver messages for (int i = 0; i &lt; internalMessages.Count; i++) { //send request Byte[] data = System.Text.Encoding.ASCII.GetBytes(internalMessages[i].GetMessage()); NetworkStream stream = internalMessages[i].GetClient().GetStream(); stream.Write(data, 0, data.Length); } internalMessages.Clear(); if (!didSomething) Thread.Sleep(1); //Nothing to receive or send, maybe tomorr... next milisec there is something to do } startOnce.ReleaseMutex(); } public void Stop() { status = "stopped"; } public Boolean Status() { return (status == "started"); } //return true if message was accepted public Boolean addMessageNonBlocking(TcpClient client, String message) { Boolean gotMutex = false; if(gotMutex = moveToInternal.WaitOne(0)); { Message tmpMessage = new Message(client, message); externalMessages.Add(tmpMessage); moveToInternal.ReleaseMutex(); } return gotMutex; } public void addMessageBlocking(TcpClient client, String message) { //loop until message is delivered while (!addMessageNonBlocking(client, message)) { Thread.Sleep(1); //could skip this, but no need for busy waiting } } private class Message { TcpClient client; String message; public Message(TcpClient client, String message) { this.client = client; this.message = message; } public TcpClient GetClient() { return client; } public String GetMessage() { return message; } } } </code></pre> <hr> <p>Test Code for verifying if TcpClient is blocking</p> <p>Add this code anywhere it can be run. testClient must be a TcpClient that is connected to anywhere.</p> <pre><code>int i = 0; String testmsg = "This is a 25 char test!!!"; Byte[] data = System.Text.Encoding.ASCII.GetBytes(testmsg); while (true) { i++; testClient.GetStream().Write(data, 0, data.Length); if (i % 10 == 0) Console.WriteLine("Cycle Count: " + i); } </code></pre>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload