views:

93

answers:

3

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.

+1  A: 

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.

deltreme
@deltreme: nicely explained and thx for your precious time as well. I have a question here. how to know which object is threadsafe and which one is not. What will happen if i takes a lock on _connection for removing an item. Then can i add another object to the same list at the same time.
Shantanu Gupta
On MSDN they usually tell you if an object is threadsafe or not. If they don't say, you should assume it isn't. You should use a lock both when you add and when you remove an item from the list, otherwise you might get unexpected results. The `Add` and `Remove` methods under the hood execute a few lines of code, and when you call them simultaneously, they might bite eachother. Putting a lock around it will make one thread wait for the other to release its lock, so they won't interfere with eachother.
deltreme
+1  A: 

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.

Nikolai N Fetissov
@Nikolai: Nice links provided. Thx
Shantanu Gupta
+1  A: 

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.

Jack Leitch
`lock (_connections) { foreach (ConnectionInfo conn in _connections) { if (conn != connection) { conn.Socket.Send( buffer, bytesRead, SocketFlags.None); } } }` This has been used to broadcast same message to every socket ? As explained in your second paragraph
Shantanu Gupta
@Jack: Great explanation, making all the points clear here. Still reading your answer along with taking article as a reference. Will back to you as i read it completely.
Shantanu Gupta
@Shantanu: Yes, that foreach loop is the one that broadcasts the received message to every other socket.
Jack Leitch
@Jack: Just read the whole article and implemented all the sections discussed here as well as in article. Your explanation was a great help along with the others help. I would also like to thank deltreme for his gud explamation also.
Shantanu Gupta