TcpClient - waiting for data to become available - c#

In my C# application, I have a thread which basically continually reads from a TcpClient until told to stop. I use WaitHandles for this purpose, for example:
private ManualResetEvent stopping;
private void Receive()
{
while (!this.stopping.WaitOne(10))
{
while (this.client.Available > 0)
{
// Read and process data
}
}
}
As you can see, I'm waiting for the thread to be told to stop. If it hasn't been, it reads all data from the TcpClient and loops.
The problem I have is the 10ms delay, which I'd rather not have. I could reduce it, but I'd prefer a solution where the program will pause until EITHER the thread is told to stop, or more data becomes available.
In effect, what I want is a WaitHandle which tells me when data is available on the TcpClient. That way, I can use WaitHandle.WaitAny. Is there any way I can do this, or can someone suggest an alternative approach?
This can't be a bodge as it needs to be a fairly performant -and- lightweight background process.

You'll need to use the BeginRead method on the underlying NetworkStream. This will return a IAsyncResult which has a AsyncWaitHandle property. Now you create an array of WaitHandle's, stick the AsyncWaitHandle in [0], the ManualResetEvent in [1] and then call WaitHandle.WaitAny() with the array, and it will either return the index of the handle that is set, or WaitTimeout on time out.
Once you know it's the AsyncHandle that's set, you can use EndRead to complete the read, and get the data into your buffer.
The help for BeginRead says you need a callback function, but you can pass Null for this and code everything in your base function if you prefer.

Related

Checking if NamedPipeClientStream has something to read

I need to check a NamedPipeClientStream to see if there are bytes for it to read before I attempt to read it. The reason for this is because the thread stops on any read operation if there's nothing to read and I simply cannot have that. I must be able to continue even if there's no bytes to read.
I've also tried wrapping it in a StreamReader, which I've seen suggested, but that has the same result.
StreamReader sr = new StreamReader(myPipe)
string temp;
while((temp = sr.ReadLine()) != null) //Thread stops in ReadLine
{
Console.WriteLine("Received from server: {0}", temp);
}
I either need for the read operations to not wait until there are bytes to read, or a way to check if there are bytes to read before attempting the read operations.
PipeStream does not support the Length, Position or ReadTimout properties or Seek...
This is a very bad pattern. Structure your code so that there's a reading thread that always tries to read until the stream has ended. Then, make your threads communicate to achieve the logic and control flow you want.
It is generally not possible to check whether an arbitrary Stream has data available. I think it's possible with named pipes. But even if you do that you need to ensure that incoming bytes will be read in a timely manner. There is no event for that. Even if you manage all of this the code will be quite nasty. It will not be easy to mentally verify.
For that reason, simply keep a reading loop alive. You could make that reading loop enqueue the data into a queue (maybe BlockingCollection). Then other threads can check that queue for data or wait for data to arrive. The stream will always be drained correctly. You can signal the stream end by enqueueing null.
When I say "thread" I mean any primitive that gives you the appearance of a thread. These days you would never use Thread. Rather, use async/await or Task.

C# timed sempahore to syncronize two threads and a single output buffer

ADDED PREFACE
Here I want better explain the scenario of my application.
I need a windows service to "convert" a SerialPort into a TCPPort. For instance let's say I have a serial ticket printer connected to a COM port for raw ascii stream and I want to access it by TCP sockets from network. The result should be that the serial printer becomes a network printer, my service should link many tcp sockets to com port.
This is the scheme:
The main problem is that the COM port has a unique connection but here I can have many simultaneous connection from network clients. I need to synchronize writes to COMport and get output from the COMport and copy that to all connected TCP clients.
With TCPconnections I cannot know when a write stream is really close, because a network client can send a print job without closing its connection and send another job after a while.
Serial printers are inline printer and there is not a start/end command, it can simply receive ascii chars and they are printer in receiving order.
This is because I need to be sure that network input will not be mixed and I want a timer that can understand that the job is really end before relase the synchronized write lock.
ORIGINAL QUESTION
I have two threads: A, B.
Both threads have to write in a single output buffer by WriteToOutput() method, and I want to be sure that the output will not be mixed if both A and B want to write in the output at the same time.
For first I need a simple semaphore:
private object locker = new object();
public void WriteToOutput(byte[] threadBuffer)
{
lock (locker)
{
//... copy threadBuffer to outputBuffer
}
}
But I need a little more safety to divide the outputs because a thread can empty its buffer but it can be filler right after the lock release.
So in case of concurrency if the thread A gets the lock, I want to wait the second thread B for while, let's say a tick of 1s. If in this time the thread A wants to write something more, it has the priority, and B has to wait another tick. If the thread A do not write for a n entire tick, then it can really relase the lock and the B thread can get the lock.
Just for correction - that's a monitor, not a semaphore.
As for the rest, this sounds like a weird multi-threaded design, and it's going to be brittle and unreliable. Make it obvious when it's safe to release the shared resource - relying on any kind of timing for synchronization is a terrible idea.
The problem is that the WriteToOutput method is obviously not a good point for the synchronization! If you need to ensure multiple writes from the same thread are serialized, you need to move your synchronization point somewhere else. Or, pass a Stream instead of byte[], and read that until it's closed inside the lock - this will effectively do the same thing, move the responsibility to the callee. Just make sure you don't lock it up forever by forgetting to close the stream :) Another alternative would be to use a BlockingCollection<byte[]>. It's hard to tell what's the best option when we don't really know what you're actually trying to do.
EDIT:
Okay, serial port communication is about the only proper use of timing like this I can think of. Of course, it can also be a bit tricky to handle the communication on a non-realtime system.
The best way to solve this would be to have a single endpoint for all your access to the serial port which would handle the communication and synchronization. Instead of calling the method from your other threads, you would just post data that the endpoint would read. However, this requires you to have a way of identifying the other threads - and I'm not sure if you have something like that (perhaps the EndPoint of the TCP socket?). The simplest way would be using the BlockingCollection:
private readonly object _syncObject = new object();
public void SendData(BlockingCollection<byte[]> data)
{
lock (_syncObject)
{
byte[] buffer;
while (data.TryTake(out buffer, TimeSpan.FromSeconds(1)))
{
// Send the data
}
}
}
This will keep reading and sending data from the queue, as long as it can get another buffer in at most second-long periods - if it takes more than a second, the method will exit and another thread will have a chance.
In the socket receive thread, you'd declare the blocking collection - this will vary based on your implementation of the receive code. If you have a single instance of some class for each of the different sockets, you can just declare it as an instance field. If not, you could use ThreadLocal. This assumes you're using manual threads, one per socket - if not, you'll need a different storage.
private readonly BlockingCollection<byte[]> _dataQueue = new BlockingCollection<byte[]>();
private void ReceiveHandler(byte[] data)
{
// This assumes the byte array passed is already a copy
_data.Add(data);
SendData(_dataQueue);
}
This is definitely not the best way to handle this, but it's certainly the simplest I can think of right now - it's barely any code at all, and it only uses lock and BlockingCollection.
I'd take a look at ReaderWriterLockSlim.
https://msdn.microsoft.com/en-us/library/system.threading.readerwriterlockslim(v=vs.110).aspx

Passing content outside of an asynchronous server socket

I'm not even sure how this would work because at its very nature an asynchronous server socket can accept multiple connections.
What I would like to do is capture content if it meets a certain format and pass it outside the server socket so that other classes can reference it. I followed the MSDN code for building a Asynchronous Server Socket. Here is the callback that reads the content.
public static void ReadCallback(IAsyncResult ar)
{
string content = String.Empty;
// Retrieve the state object and the handler socketH:\JCI\BWSI\Integrations\Middleware\Jci\Jci\Framework.Jci.EventEngine\EventEngineRTLSEvents.cs
// from the asynchronous state object.
StateObject state = (StateObject)ar.AsyncState;
Socket handler = state.workSocket;
// Read data from the client socket
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data recieved so far.
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read more data.
content = state.sb.ToString();
if (content.IndexOf('\u001c') > -1)
{
// ALl the data has been read from the
// client. Display it on the console.
Console.WriteLine(
"Read {0} bytes from socket. \n Data : {1}", content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data recieived. Get more.
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
}
If I understand the question correctly, the basic issue is this: when some data is received on the socket, that results in some new object being created in your program, and you want some code to operate on this object to process it in some way.
So, let's think about it this way: when you want some code to execute, how do you make that happen? Since in C# all code exists in methods, you need to call a method to make the code execute.
Now, in the scenario of an asynchronously handled socket, you have some options. Code always executes in the context of a thread, so you need to think about which thread you want to execute this particular code. That really amounts to there being just two options: 1) execute in the current thread, or 2) execute in a different thread.
Okay, now we're getting somewhere. If we pick option #1, how does that happen? Easy...just call the method from your ReadCallback() method. If you've created an object you want that called method to process, just pass that object to the method when you call it.
And it really is that simple (*).
Now, what if you want to pick #2? Well…that's a bit more complicated. First, you need to find a thread to execute the code, and second you need to get the data to that thread.
I can think of at least three obvious ways to go about this:
Use an existing UI thread. In this case, you'll use e.g. the Control.Invoke() method or Dispatcher.Invoke() (for Winforms or WPF, respectively). A similar mechanism is available in ASP.NET.
Use the thread pool, e.g. via the Task Parallel Library. For example, you might use the Task.Run() method to start a new task.
Use a producer/consumer implementation, in which you've previously started a thread dedicated just to consuming the data objects created when receiving data. For example, you could start a new thread with a method that just uses foreach to pull items from a BlockingCollection<T> instance, while the ReadCallback() method adds items to that same instance.
In the first two options above, data moves to the other thread via an argument to the method being invoked, or as a captured variable in an anonymous method being invoked (I find the latter more convenient than the former, but either works fine). In the third option, obviously the data moves from the socket's thread to the consuming thread via the shared collection.
I hope that the above is enough to get you pointed in the right direction. As asked, the question is fairly broad (possibly too broad), but I think what I've written here is still reasonably concise, with just enough vagueness to remain applicable to whatever your scenario is, without being so vague as to be non-useful. :)
(*) Actually, it's a little more complicated than that, in that you have a number of mechanisms by which you can call a method. The simplest is that the method name is hard-coded into your ReadCallback() method; you just call the one method you know you always want to call. But that limits reusability of the code, and couples it to unrelated code which makes it harder to maintain.
Other options include:
Declaring an event on your socket client object where the ReadCallback() method exists, and have the object that's supposed to actually process the data subscribe to that event. The ReadCallback() method would raise the event, passing the object to process as part of the event's arguments.
Simply passing a callback delegate to the socket client object, very much in the same way you currently pass a delegate representing your ReadCallback() method to the socket class.
First off, this is not really intended to be an answer, but I find that writing a lot of text as comments is problematic.
I've now actually taken a look at your code, and maybe I'm beginning to understand what you're asking. Your use of the phrase "pass it outside the server socket" is partly what confused me - what you mean is "give the data to a method that is not a dedicated part of the Socket processing code", right?
The simple way to do this is, once you've accumulated a complete "logical message" is to call a method to process it from your asynchronous ReadCallback method. So the business logic is actually running as a subroutine of the Socket code. But this is only OK for trivial processing that does not block for any length of time.
A more common technique is to use multi-threading and cross-thread dispatching techniques. Then the business logic is semi-independent of the Socket code. There are many possible ways of doing this. I've written code that explicitly uses an AutoResetEvent and a queue of messages (with a lock), but it is a bit messy. The modern way (which I've not used personally) is via the C# async and await facility.
Finally, a few comments on the code you present. It is safer to not use an end-of-file token, and instead prefix each logical message with a message length, for example an Int32 encoded/decoded via BitConverter to a 4-byte array (be careful of big endian vs. little endian). The problem with the end-of-file marker is that it is conceivable that the marker could be split between two calls to your ReadCallback method.
Similarly, it is best to first accumulate the entire message as raw bytes, and then decode the whole message back to string. Again, the problem could be that a UTF-8 two-byte sequence could get split across two calls to ReadCallback.
Hope this helps.
EDIT:
Just want to mention that the fact that TCP/IP input is considered to be a stream of bytes does make the processing tricky. I've already indicated that a length prefix is safer than an end-of-file token, and that accumulating the whole message before converting from UTF-8 to string is safer than converting individual segments.
But in addition you have to be careful that you have at least 4 bytes before you try to convert it into the length. It is conceivable that you get one message plus the first 2 bytes of the next one, so you only have half of the length prefix for the second message. Then you have to just save those 2 bytes and wait for the next call before you can even convert the length.
Normally you get a whole message on each call, and it is very rare that this streaming causes problems. And it never happens during testing. But according to Murphy's law eventually it will happen, and at the worst possible time.

How safe are Interlocked.Exchange?

Beeing a threading noob, I'm trying to find a way w/o locking objects that allows me to enqueue a threadpool task, in such way that it has a max degree of parallelism = 1.
Will this code do what I think it does?
private int status;
private const int Idle = 0;
private const int Busy = 1;
private void Schedule()
{
// only schedule if we idle
// we become busy and get the old value to compare with
// in an atomic way (?)
if (Interlocked.Exchange(ref status, Busy) == Idle)
{
ThreadPool.QueueUserWorkItem(Run);
}
}
That is, in a threadsafe way enqueue the Run method if the status is Idle.
It seems to work fine in my tests, but since this is not my area, I'm not sure.
Yes, this will do what you want. It will never allow you to get a return value of Idle when in fact status is Busy, and it will set status to Busy in the same operation, with no chance of a conflict. So far so good.
However, if you're using a ConcurrentQueue<T> later on, why do you even do this? Why do you use a ThreadPool to enqueue Run over and over again, instead of just having a single thread continually take data from the concurrent queue using TryDequeue?
In fact, there is a producer-consumer collection that is specifically designed for this, the BlockingCollection<T>. Your consumer thread would just call Take (with a cancellation token if necessary - probably a good idea) and that either returns a value as in ConcurrentQueue<T>; or if no value is available, blocks the thread until there is something to take. When some other thread adds an item to the collection, it will notify as many consumers as it has data for (in your case, no need for anything complex, since you only have one consumer).
That means you only have to handle starting and stopping a single thread, which will run an "infinite" cycle, which will call col.Take, while the producers call col.Add.
Of course, this assumes you have .NET 4.0+ available, but then again, you probably do, since you're using ConcurrentQueue<T>.

What can happen in two concurrent NetworkStream.BeginWrite calls?

I have two methods on my Sender class:
public void SendMessage(OutgoingMessage msg)
{
try
{
stream.BeginWrite(msg.TcpData, 0, 16, messageSentCallback, msg);
}
catch
{
// ...
}
}
private void messageSentCallback(IAsyncResult result)
{
stream.EndWrite(result);
if (result.IsCompleted)
onDataSent(result.AsyncState as OutgoingMessage);
}
Other parts of the program can call (if they have an access to the Sender) the SendMessage() method. Since the program works in multi-threading environment, multiple threads have access to the Sender object.
I have 2 questions:
Q1) Would making two concurrent calls to the SendMessage method be able to mess up the TCP communication (by filling the TCP outgoing buffer with mixed data)?
Q2) Would enclosing the stream.BeginWrite() call into the lock { } solve this problem?
As far as I understand, the call to BeginWrite simply stores the data into the TCP outgoing buffer. Is that right?
Yes, a lock is required to avoid problems. However, I would switch to a different approach, both to solve concurrency problems as well as to make the thread interaction more easy to reason about.
You could have a shared queue where several threads put requests that need to be written to the stream. A single thread then reads requests from the queue and makes write operations. Now it's much easier to understand what is going on and you don't have to worry about synchronizing the writes. You could use one of the concurrent collections like ConcurrentQueue.
MSDN Says
As long as there is one unique thread for the write operations and one
unique thread for the read operations, there will be no
cross-interference between read and write threads and no
synchronization is required.
Which means that if you have more than one threads sending data then you should use lock to make sure only one thread calls BeginWrite at a time in order to send data without any interference
If you would like to minimize blocking and maintain high concurrency with multiple writer threads I would recommend using the Socket.SendAsync which accepts a SocketAsyncEventArgs.
You could preallocate a number of SocketAsyncEventArgs (with its associated buffer space) that are used as writers, in which case, rather than having a lock you would have a SemaphoreSlim which would allow a number of 'simultaneous' writes pushing the synching lower down the protocol stack.
Here is a Code Gallery sample that could get you started (also demonstrates pooling for your buffers.)
Here is a codeproject article that also demonstrates its use.
Good luck!

Categories

Resources