2014-02-14 43 views
0

昨天我遇到了一个奇怪的问题,这让我颇为头疼。我有一个服务器应用程序与一个服务器类,而这又是从一个连接类派生。 Connection类提供有关连接状态和可能性的信息,收于实际发送数据锁定专用锁对象导致死锁

private void ConnectAndPollForData() 
{ 
    try 
    { 
     TcpListener listener = new TcpListener(Port); 

     listener.Start(); 
     while (true) 
     { 
      connection = listener.AcceptSocket(); 

      string currentBuffr = string.Empty; 
      const int READ_BUFFER_SIZE = 1024; 
      byte[] readBuffr = new byte[READ_BUFFER_SIZE]; 

      while (Connected) 
      { 
       int bytesReceived; 

       lock (lockObject) 
       { 
        bytesReceived = connection.Receive(readBuffr, READ_BUFFER_SIZE, SocketFlags.None); 
       } 
       currentBuffr += ASCIIEncoding.ASCII.GetString(readBuffr, 0, bytesReceived); 

       //do stuff 

     } 
    } 
    catch(ThreadAbortException) 
    { 
     Thread.ResetAbort(); 
    } 
    finally 
    { 

    } 
} 

public void SendString(string stringToSend) 
{ 
    stringToSend += "\r\n"; 


    if(Connected) 
    { 
     lock(lockObject) 
     { 
      connection.Send(ASCIIEncoding.UTF7.GetBytes(stringToSend)); 
     } 
    } 

} 

还有就是连接对象没有其他明确的接入连接

public bool Connected 
{ 
    get 
    { 
     if (connection != null) 
     { 
      lock (lockObject) 
      { 
       bool blockingState = connection.Blocking; 

       try 
       { 
        connection.Blocking = false; 
        connection.Send(new byte[1], 1, 0); 
       } 
       catch (SocketException e) 
       { 
        if (!e.NativeErrorCode.Equals(10035)) 
        { 
         return false; 
        } 
        //is connected, but would block 

       } 
       finally 
       { 
        connection.Blocking = blockingState; 
       } 

       return connection.Connected; 

      } 

     } 

     return false; 
    } 
} 

public virtual void CloseConnection() 
{ 
    if (Connected) 
    { 
     lock (lockObject) 
     { 
      connection.Close(); 
     } 
    } 
} 

服务器类是resonsible。 ConnectAndPollForData函数在单独的线程中执行。每当我运行这个版本的主机(我目前使用的是非线程安全的版本,这会导致其他问题),它会在通过TCP接收到很多行之后挂起。暂停调试器向我显示,一个线程尝试使用Connected的锁执行代码,而另一个尝试在ConnectAndPollForData的锁中接收数据。这种行为对我来说似乎很奇怪,因为我期望在第一个锁内执行代码,然后执行第二个锁。在使用Deadlocking lock() method'Deadlock' with only one locked object?等回调时,似乎出现了类似的问题,但这里的情况有些不同,因为在我的情况下(我认为)锁内的代码不应发出任何自己试图获得锁的事件物体。

回答

4

我们假设它首先获得第二种方法的锁定。所以它是持有锁,并等待数据。目前还不清楚这是否是直接接收第一种方法发送的数据,或者是否正在寻找来自不相关服务器的回复 - 在第一种方法中回复消息发送。但无论哪种方式,我假定在发送出站消息之前不会有数据传入。

现在考虑:出站邮件不能发送,因为您持有排他锁。

所以是的,你已经陷入僵局。基本上,不要这样做。即使在同一个套接字上,也不需要在入站和出站套接字操作之间进行同步。因为在同一个套接字或并发编写器上同时存在并发阅读器是没有意义的,所以我猜你实际上并不需要这些。