Production ready, multi-threaded c# http server - c#

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?

Related

Cross-Thread access of a field in C#

If a class has an array, it doesn't really matter what of. Now one thread is adding data to said array, while another thread needs to process the data that is already in it. With my limited knowledge of multithreading, how could this work? The first problem I can think of is if an item is added while the other thread is processing what's still there. At first I thought that wouldn't be a problem, the processor thread would get it next time it processed, but then I realized that while the processor thread removes items it's already processed, the adding thread would not receive this change, possibly (?) wreaking havoc. Is there any good way to implement this behavior?
What you've described is basically the Reader Writers Problem. If you want to take care of multithreading, you're either going to need a concurrent collection, or use of a lock. The simplest implementation of a lock would just be locking an object
private Object myLock = new Object();
public MyClass ReadFromSharedArray()
{
lock(myLock)
{
//do whatever here
}
}
public void WriteToSharedArray(MyClass data)
{
lock(myLock)
{
//Do whatever here
}
}
There are better locks such as ReadWriterSlim locks but this sort of basic implementation should be a good starting point.
Also you mentioned adding/removing from arrays, I'm assuming you meant Lists (or better yet a Queue) - there's a ConcurrentQueuewhich could be a good replacement.

It is ok to store a Thread in a static variable?

I want to make sure that I always create only one instance of a Thread so I built this:
private static volatile Thread mdmFetchThread = null;
private static object Locker = new object();
public void myMethod(){
string someParameter = getParameterDynamically();
lock(Locker)
{
// If an mdmFetchThread is already running, we do not start a new one.
if(mdmFetchThread != null && mdmFetchThread.ThreadState != ThreadState.Stopped)
{
// warn...
}
else
{
mdmFetchThread = new Thread(() => { doStuff(someParameter); });
mdmFetchThread.Start();
}
}
}
Is this ok to do or what could be possible pitfalls?
//Edit: As requested below a bit context: doStuff() is calling some external system. This call might timeout but I cant specify the timeout. So I call it in mdmFetchThread and do a mdmFetchThread.join(20000) later. To avoid that I call the external system twice, I created the static variable so that I can check if a call is currently ongoing.
Storing a thread in a static variable is OK (if you need at most one such thread per AppDomain). You can store whatever you want in static storage.
The condition mdmFetchThread.ThreadState != ThreadState.Stopped is racy. You might find it to be false 1 nanosecond before the thread exits. Then you accidentally do nothing. Maintain your own boolean status variable and synchronize properly. Abandon volatile because it is more complicated than necessary.
Consider switching to Task. It is more modern. Less pitfalls.
Consider using a Lazy<Task> to create the singleton behavior you want.
Add error handling. A crash in a background thread terminates the process without notifying the developer of the error.
Generally speaking if you are using statics to store state (such as a thread), then you might have a design flaw when attempting to scale out or when trying to manage the lifetime of the object. I usually try to avoid statics whenever possible.
An alternative might be to create a class that only manages a single thread to perform your task as an instance. This class might be responsible for passing data to your Thread or managing the state of it. For example, ensuring it is only run once, stopping the thread gracefully, or handling when the thread completes. If you wanted to scale out, then you'd just create multiple instances of your class each with their own thread that they manage. If you only wanted one, then just pass around a single instance.
If you're looking for ways to make this instance available to your entire application (which is usually the issue people are trying to solve when using static variables), then take a look into patterns like using ServiceContainers and IServiceProvider.

Is this a correct use of multithreading design? (C#)

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.

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!

C# working with singleton from two different threads

I am using the singleton pattern in a wpf app, but having doubts about how to make it work with multiple threads.
I have a class called Monitor which maintains a list of "settings" to watch, for different "devices". Outline shown below.
On my main thread I am doing
Monitor.getMonitor.register(watchlist) or Monitor.getMonitor.unregister(...) depending on the user input and I have a DispatchTimer running every 200ms that does a
Monitor.getMonitor.update()
public class Monitor
{
private Hashtable Master; //key=device, value=list of settings to watch
private static Monitor instance = new Monitor();
private Monitor() {}
public static Monitor getMonitor()
{
return instance;
}
public void register(watchlist){...}
public void unregister(...){...}
public void update(){...}
}
register()/unregister() perform add/remove to the hastable.
update() is only reading stuff out of the hashtable.
Depending on the number of devices and settings, update() is going to be iterating over the hastable and it contents, getting the latest values.
The main thread maybe calling register and unregister quite often and I want the gui to stay responsive. Whats a good way to do this?
Do I lock the hashtable, around add/remove and iterate, OR just surrond the iteration part in update with a try catch (ala gracefully fail) to catch any weird state the hashtable might get into(no locking) or is there some better way to do this (if update fails no prob..its going to be running in 200ms again anyway).
Not very sure about what is going on, cause the code as is hasnt really shown any problems which itself is making me a bit uneasy cause it just seems wrong. Thanks for any suggestions...
See my article on singleton implementations to make the singleton fetching itself threadsafe.
Yes, you'll need to lock when you modify or iterate over the hashtable. You could use a ReaderWriterLock (or preferrably ReaderWriterLockSlim in .NET 3.5) to allow multiple readers at a time. If you need to do a lot of work while you're iterating, you could always lock, take a copy, unlock, and then work on the copy - so long as the work doesn't mind the copy being slightly stale.
(If you're using .NET 2.0+, I'd suggest using the generic collections such as Dictionary<TKey, TValue> instead of Hashtable. I'd also suggest you rename your methods in line with .NET conventions. That code's got a distinct Java accent at the moment ;)
Yes, you should lock each operation:
public class Monitor
{
private Hashtable Master; //key=device, value=list of settings to watch
...
private object tableLock = new object();
public void register(watchlist)
{
lock(tableLock) {
// do stuff
}
}
}
You shouldn't consider using a try/catch block - exceptions shouldn't be considered as a "normal" situation, and you might end up with a corrupted object state without any exception.
How many rows are there? Unless the update() loop takes a long time to do the iterations, I'd probably lock. If the main thread is potentially doing a lot of register/unregister calls, then update might fail repeatedly -- if it fails for 20 or 30 consecutive calls, is that a problem?
That code looks ok to me. I'd probably make the class sealed. I'd also use a typed dictionary vs. a Hashtable.

Categories

Resources