2014-02-14 132 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

我們假設它首先獲得第二種方法的鎖定。所以它是持有鎖,並等待數據。目前還不清楚這是否是直接接收第一種方法發送的數據,或者是否正在尋找來自不相關服務器的回覆 - 在第一種方法中回覆消息發送。但無論哪種方式,我假定在發送出站消息之前不會有數據傳入。

現在考慮:出站郵件不能發送,因爲您持有排他鎖。

所以是的,你已經陷入僵局。基本上,不要這樣做。即使在同一個套接字上,也不需要在入站和出站套接字操作之間進行同步。因爲在同一個套接字或併發編寫器上同時存在併發閱讀器是沒有意義的,所以我猜你實際上並不需要這些。