Skip to main content
 首页 » 编程设计

c#之如何使用多线程、锁、Socket编程

2024年02月24日46emanlee

在过去的 48 小时里,我一直在努力理解多线程 和Socket 编程。我尝试实现套接字编程并在不使用多线程时取得了成功。我对这两个主题都不熟悉,并且提出了 2-3 个关于堆栈本身的问题,需要同样的帮助。

经过大量谷歌搜索后,我发现了一个 article 解释了Socket Programming和Multithreading,但是我对这篇文章还是有很多疑惑,卡在了图5文章。

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); 
        } 
    } 

在最后一行中,您可以看到一个锁已被占用,并且 delegate ProcessConnection 上方的 3-4 行已被绑定(bind)。

在这一点上,我不清楚这个锁是如何工作的。当锁被占用时,幕后发生了什么?为什么作者在这里使用锁?如果没有锁定会发生什么?线程 ProcessConnection 是如何工作的?什么事情同时发生?

我对所有这些问题感到困惑

我知道这里有一个问题列表,但如果你能帮助我理解使用多线程的方法,那将是一个很大的帮助。

请您参考如下方法:

connection.Thread.Start(connection) 通过调用 ProcessConnection 启动一个新线程,传递 connection 作为 state 参数。当前线程中的执行会立即继续下一行,而 ProcessConnection 会在新线程中执行。

ProcessConnection从AcceptConnections传递给它的ConnectionInfo对象中获取Socket对象,等待接收数据从 socket 。当它接收到数据时,它会遍历 connections 集合中的所有其他 ConnectionInfo 对象,并将此数据按顺序发送给它们中的每一个。

那么这里同时运行的是什么?嗯,我们有初始线程(称之为线程 0)在无限循环中执行 AcceptConnections。然后对于我们接受的每个套接字连接,我们都有一个线程执行 ProcessConnection。

需要锁是因为 ProcessConnection 使用 foreach 循环遍历已知连接以向它们发送数据。如果线程 0 在 foreach 中枚举集合时向集合添加新连接,则 InvalidOperationException 将在 ProcessConnection 中抛出.

lock 确实可以防止这种情况下的并发问题,但它也会导致潜在的性能问题。它不仅可以防止 AcceptConnections 在 ProcessConnection 枚举集合时修改集合。它还可以防止任何两个执行 ProcessConnection 的线程同时枚举集合。在这种情况下更好的选择是 ReaderWriterLockSlim这将允许多个线程同时读取集合。