How to use Multithreading, locks, Socket Programming

非 Y 不嫁゛ 提交于 2019-12-04 19:28:25

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.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!