I'm building a small chat program that consists of a server and client. The server keeps a list of clients that it interacts with.
I've got two worker threads on the server. One handles incoming client connections. The other handles incoming client messages.
Now, since both threads interact with a List called 'clients', I've done something like this.
// The clients list looks something like this...
List<TcpClient> clients;
// This is running on one thread.
ConnectionHandler()
{
while(true)
{
// Wait for client to connect, etc. etc.
// Now, add the client to my clients List.
lock(clients)clients.Add(myNewClient);
}
}
// This is running on another thread.
ClientHandler()
{
while(true)
{
lock(clients)
{
/*
This will be handling things like incoming messages
and clients disconnecting (clients being removed from
the 'clients' List
*/
}
}
}
Is this a correct use of locks to prevent my List from being altered by two different threads at once?
I haven't had any problems doing this so far, but I just want to make sure it's correct.
This is correct, but make sure that ClientHandler does not hold the lock for too long. It should never hold the lock while blocking (e.g. caused by an IO operation on a socket). If you violate this rule you will find your throughput being destroyed (still maintaining correctness).
Do you have single writer and multiple readers? Have a look at ReaderWriterLock and this collections.
Looks kinda OK. Chat servers are periously tricky for multithreadedly-challenged. Exceptions could be raised inside locks, for example, when a server-client socket object gets a disconnect but, before its thread can remove the object from the list, another thread locks the list and tries to write to the disconnected socket.
A note (on top) - since you don't initialize the field (ie I don't see how you do it, when you might destroy and re-initialize etc.) - make sure you're locking the same instance, e.g. see this Lock on an object that might change during code execution
Looks fine to me but I would make this correction:
private readonly List<TcpClient> clients = new List<TcpClient>();
You can also create the list in the constructor but keep it as readonly. This is key to make sure you're locking on the same object. Otherwise, if you happen recreate clients list, your code would stop being thread safe.
Related
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
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions concerning problems with code you've written must describe the specific problem — and include valid code to reproduce it — in the question itself. See SSCCE.org for guidance.
Closed 9 years ago.
Improve this question
I'm creating a client-server structure where the server has a thread for every client.
That specific thread only sends and receives data. In the main thread of the server I'd want to read the input that the clientthread received. But it's possible that that input is being modified by the clientthread at the same time the mainthread is reading. How would i prevent this? I have read on locks but have no idea how to implement them that way.
A second part of my question is: the clientthread is a loop that constantly reads from a networkstream, and thus blocks that thread until it can read something. But can i call a function from my main thread (that function would send something through that networkstream) that the existing clientthread (that is looping) must execute?
Sorry i can't give any code right now, but i think it's clear enough?
It sounds like a producer-consumer design might be a good fit for your problem. In general terms, the client threads will put any received data into a (thread safe) queue and not modify it after that - any new data that arrives will go to a new slot in the queue. The main thread can then wait for new data in any of the queues and process it once it arrives. The main thread could either check on all the queues periodically, or (better) receive some sort of notification when data is placed in a queue, so that it can sleep while nothing is happening and won't eat CPU time.
Since you ask about locks: Here is a basic lock-based implementation as an alternative to queues, perhaps that will help you understand the principle
class IncomingClientData
{
private List<byte> m_incomingData = new List<byte>();
private readonly object m_lock = new object();
public void Append(IEnumerable<byte> data)
{
lock(m_lock)
{
m_incomingData.AddRange(data);
}
}
public List<byte> ReadAndClear()
{
lock(m_lock)
{
List<byte> result = m_incomingData;
m_incomingData = new List<byte>();
return result;
}
}
}
In this example, your client threads would call Append with the data that they have received, and the main thread could collect all the rececived data that arrived since the last check by calling ReadAndClear.
This is made thread-safe by locking all the code in both functions on m_lock, which is just a regular plain object - you can lock on any object in C#, but I believe this can be confusing and actually lead to subtle bugs if used carelessly, so I almost always use a dedicated object to lock on. Only one thread at a time can hold the lock on an object, so the code of those functions will only run in one thread at a time. For example, if your main thread calls ReadAndClear while the client thread is still busy appending data to the list, the main thread will wait until the client thread leaves the Append function.
It's not required to make a new class for this, but it can prevent accidents, because we can carefully control how the shared state is being accessed. For example, we know that it is safe to return the internal list in ReadAndClear() because there can be no other reference to the same list at that time.
Now for your second question: Just plain calling a method won't ever cause the method to run on a different thread, no matter which class the method is in. Invoke is a special feature of the WinForms UI thread, you'd have to implement that functionality yourself if you want to Invoke something in your worker threads. Internally, Invoke works by placing the code you want to run into a queue of all things that are supposed to run on the UI thread, including e.g. UI events. The UI thread itself is basically a loop that always pulls the next piece of work from that queue, and then performs that work, then takes the next item from the queue and so on. That is also why you shouldn't do long work in an event handler - as long as the UI thread is busy running your code, it won't be able to process the next items in its queue, so you'll hold up all the other work items / events that occur.
If you want your client threads to run a certain function, you have to actually provide the code for that - e.g. have the client threads check some queue for commands from the main thread.
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!
I implemented an HTTP server in c# .NET:
public class HttpServer
{
private HttpListener listener;
public HttpServer()
{
listener = new HttpListener();
listener.Prefixes.Add("http://localhost:8080/");
}
public void Start()
{
lock(this) {
listener.Start();
AsyncProcessing(listener);
}
}
public void Stop()
{
lock (this) {
listener.Stop();
}
}
private void AsyncProcessing(HttpListener listener)
{
if (listener == null)
return;
listener.BeginGetContext(new AsyncCallback(Callback), listener);
}
private void Callback(IAsyncResult result)
{
HttpListenerContext context = null;
lock(this) {
HttpListener listener = (HttpListener)result.AsyncState;
if (!listener.IsListening)
return;
context = listener.EndGetContext(result);
AsyncProcessing(listener);
}
/* handle request */
}
}
I have some questions about this implementation:
I added some locks here and there to prevent race conditions, but I'm confused: Are those really needed? I read in the documentation that all public non-static methods are NOT thread safe. Why haven't I seen code where this fact is considered?
How does the HttpListenerContext behave? Does he have some sort of connection to the HttpListener? Or can I use multiple HttpListenerContexts concurrently?
I heard HttpListener wouldn't be ready for production systems, but I've never seen an argument supporting this claim. Is it true or not?
Are there other things I should consider which I haven't mentioned?
Thanks for your ideas
Bear in mind that I'm no expert in multithreading, so you should take care to verify, as best as you can, anything I say.
If anyone else knows, and would like to just steal my entire answer and just edit in or correct the details, feel free to do that.
Let's deal with your questions one by one:
I added some locks here and there to prevent race conditions, but I'm confused: Are those really needed? I read in the documentation that all public non-static methods are NOT thread safe. Why haven't I seen code where this fact is considered?
Well, yes and no. Locks are typically used to prevent multiple threads to access the same data structure at the same time, since it would corrupt the data structure. Consider sorting an array on one thread and inserting an element in the middle in another, timing those two threads correct would corrupt the contents of the array.
Now, in your code you are locking on this which is never a good idea. Outside code might also take a lock on the same object, and that's out of your control, so in the interest of creating production ready code, I would not do that.
If you need locks in your code, I would construct specific lock objects and use those.
In other words, add this:
private readonly object _Lock = new object();
and then everywhere you have lock(this) replace it with lock(_Lock) instead. This way you can also have multiple locks, if needs be.
As for actually needing locks, I'm not 100% sure on that. The thing I'm not sure about is that you're locking before calling Stop, and you're locking in the callback and inside the lock you check if the listener is still running.
This will prevent you from stopping the listener after accepting a request, but before you've actually processed the request. In other words, it sounds like you would prevent closing the server with open requests still being handled.
But, no, you wouldn't prevent that, because you might stop the server after leaving the locked section in the callback, but during or before the commented code has fully executed, so you would still have that problem.
However It will also mean you've effectively serialized some of the callback method, the part where you call EndGetContext and restart the BeginGetContext cycle. Whether this is a good pattern or not, I don't know.
How does the HttpListenerContext behave? Does he have some sort of connection to the HttpListener? Or can I use multiple HttpListenerContexts concurrently?
Here I will make a guess. That class has no reference back to the listener class, or, it has a thread-safe way of cooperating with it.
It wouldn't be much of a thread-based http listener system if every access to the request/response data has to be serialized.
In any case, if in doubt, check the documentation of the methods and/or properties on the context class that you're accessing, and if you need to take steps to ensure thread safety, the documentation will say so.
I heard HttpListener wouldn't be ready for production systems, but I've never seen an argument supporting this claim. Is it true or not?
(see comment on question)
Are there other things I should consider which I haven't mentioned?
Multi-threaded code is hard to write. Judging by your question I would venture a guess that you haven't done a lot of it, and to be honest, though I have done a lot of it, I still feel like I'm on thin ice.
My advice is thus as follows:
Do you really need multi-threading?
Do you have other colleagues that know more about this that could help you?
For last 48 hours, I have been trying to understand Multithreading and Socket Programming. I tried to implement socket programming and had success when not using multithreading. I am new to both of the topics and have raised 2-3 question on stack itself needing help on the same.
After googling a lot I found an article that explains Socket Programming and Multithreading, but I still have a lot of doubts in this article and got stuck at Figure 5 in the article.
private void AcceptConnections()
{
while (true)
{
// Accept a connection
Socket socket = _serverSocket.Accept();
ConnectionInfo connection = new ConnectionInfo();
connection.Socket = socket;
// Create the thread for the receives.
connection.Thread = new Thread(ProcessConnection);
connection.Thread.IsBackground = true;
connection.Thread.Start(connection);
// Store the socket
lock (_connections) _connections.Add(connection);
}
}
In the very last line you can see a lock has been taken and 3-4 lines above a delegate ProcessConnection is bound.
At this point, I am not clear how this lock is working. What is happening behind the scenes when the lock has taken? Why did the author use lock here? What would have happened if no lock was taken? How does the thread ProcessConnection work? What things are happening simultaneously?
I got confused with all these questions
I know there is a list of questions here, but it would be a great help if you could assist me in understanding the methodology of working with multithreading.
connection.Thread.Start(connection) starts a new thread with a call to ProcessConnection, passing connection as the state argument. Execution in the current thread continues immediately with the next line while ProcessConnection is executed in the new thread.
ProcessConnection gets the Socket object from the ConnectionInfo object passed to it by AcceptConnections and waits to receive data from the socket. When it receives data, it loops through all of the other ConnectionInfo objects in the connections collection and sends this data to each of them in sequence.
So what's running concurrently here? Well, we have the initial thread (call it Thread 0) executing AcceptConnections in an endless loop. And then for each socket connection that we've accepted, we have a thread executing ProcessConnection.
The locks are needed because ProcessConnection uses foreach to loop through the known connections to send them data. If Thread 0 were to add a new connection to the collection while the collection is being enumerated in the foreach, an InvalidOperationException would be thrown in ProcessConnection.
The lock does prevent the concurrency issue in this case, but it also causes a potential performance problem. It doesn't only prevent AcceptConnections from modifying the collection while ProcessConnection is enumerating it. It also prevents any two threads executing ProcessConnection from enumerating the collection at the same time. A better choice in this case would be a ReaderWriterLockSlim which would allow multiple threads to read the collection concurrently.
I'm assuming _connections is a List<ConnectionInfo>: Lists are not threadsafe, and this thread adds items to that list. If another thread would be removing an item at the same time, the results would be unpredictable. So you have to make sure no other process can access it, using a lock.
connection.Thread.Start(connection); starts a new Thread that will start immediately or some time soon. The current thread (the code you're seeing here) will not have any control over it. This new thread is provided with a ConnectionInfo object though, so it will know on what socket to perform tasks on. While the current thread keeps listening to new clients, the ProcessConnection function will handle the recently accepted client.
In C#, and I think in CLR in general, every object might have a monitor associated with it. Here _connections is a collection that is possibly shared with the threads started from this very function (they probably remove connections from the collection when they are done). Collections in C# are not synchronized by default, you have to do it explicitly, thus the lock(_connections) statement to prevent races on the collection.