2013-02-04 39 views
0

我有一個應用程序使用異步套接字與開始/結束設計模式。如何正確處理多線程/異步應用程序中的對象?

每當我收到一個新的連接,我創建一個對象並將其存儲在一個集合中。這個對象還將套接字連接存儲在它自己內部,並將在begin方法「對象狀態」中傳遞。

現在服務器異步運行,發送,接收等,有多個代碼路徑在任何給定的時間執行的對象。

我不明白的是: 如果我調用傳入當前對象和另一個線程中的函數,該對象剛剛處理完畢,那麼當前執行代碼內部的另一個對象會發生什麼情況。

編輯:

前)如果你看一下ReadDataCallback()在那裏調用doSomthing()。如果它打算用我的「設備」對象調用doSomthing(),但相應的設備在SendCallback()中有一個異常。該設備對象中的哪個狀態即將調用doSomthing()?

這是一個代碼示例。

void waitForData(MyDevice device) 
{ 
    try 
    { 
     if (device.SocketState.IsSSL) 
     { 
      device.SocketState.sslStream.BeginRead(device.SocketState.DataBuffer, 0, device.SocketState.DataBuffer.Length, m_readDataCallback, device); 
     } 
     else 
     { 
      device.SocketState.DeviceSocket.BeginReceive(device.SocketState.DataBuffer, 0, device.SocketState.DataBuffer.Length, SocketFlags.None, m_readDataCallback, device); 
     } 
    } 
    catch (SocketException se) 
    { 
     DisconnectAndRemove(device); 
    } 
} 

public void ReadDataCallback(IAsyncResult ar) 
{ 
    MyDevice device = (MyDevice)ar.AsyncState; 
    try 
    { 
     Queue<kustompacket> qps = null; 
     int iRx = 0; 

     if (device.SocketState.IsSSL) 
     { 
      iRx = device.SocketState.sslStream.EndRead(ar); 
      if (iRx == 0) 
      { 
       DisconnectAndRemove(device); 
      } 
      else if (iRx > 0) 
      { 
       device.CircularBuff.Add(iRx, device.SocketState.DataBuffer); 
       qps = device.CircularBuff.ReadPackets(); 
       doSomthing(device); 
      } 
     } 
     else 
     { 
      if (device.SocketState.DeviceSocket != null) 
      { 
       if (device.SocketState.DeviceSocket.Connected) 
       { 
        // Read data from the client socket. 
        iRx = device.SocketState.DeviceSocket.EndReceive(ar); 
        if (iRx == 0) 
        { 
         DisconnectAndRemove(device); 
        } 
        else if (iRx > 0) 
        { 
         device.CircularBuff.Add(iRx, device.SocketState.DataBuffer); 
         qps = device.CircularBuff.ReadEncryptedPackets(device.SocketState.SessionID); 
         doSomthing(device); 
        } 
       } 
      } 
     } 

     if (qps != null) 
     { 
      MyDelegate meh = new MyDelegate(HandleDataReceived); 
      meh.BeginInvoke(device, qps, null, null); 
     } 

     if (iRx != 0) 
     { 
      waitForData(device); 
     } 
    } 
    catch (ObjectDisposedException ode) 
    { 
     //Socket has been closed 
     //DisconnectAndRemove(device); 
    } 
    catch (SocketException se) 
    { 
     //if (se.ErrorCode == 10054) // Error code for Connection reset by peer 
     //{ 
     DisconnectAndRemove(device); 
     //} 
    } 
    catch (Exception ex) 
    { 
     DisconnectAndRemove(device); 
    } 
} 


public void SendCallback(IAsyncResult ar) 
{ 
    MyDevice device = (MyDevice)ar.AsyncState; 
    try 
    { 
     // Complete sending the data to the remote device. 
     if (device.SocketState.IsSSL) 
     { 
      device.SocketState.sslStream.EndWrite(ar); 
     } 
     else 
     { 
      int bytesSent = device.SocketState.DeviceSocket.EndSend(ar); 
     } 
     device.ResetAge(); 
    } 
    catch (SocketException se) 
    { 
     DisconnectAndRemove(device); 
    } 
    catch (Exception ex) 
    { 
    } 

    if (device.SocketState.IsSSL) 
    { 
     device.Write(); 
    } 
} 
+0

如何發佈描述你在說什麼的代碼示例? –

+0

如果我們在查看代碼而不是口頭解釋你所做的事情,那真的會更容易回答。 –

+0

我發佈了一個我的代碼的例子。如果您查看它調用doSomthing()的ReadDataCallback()。如果它打算用我的「設備」對象調用doSomthing(),但相應的設備在SendCallback()中有一個異常。該設備對象中的哪個狀態即將調用doSomthing()? – Mausimo

回答

0

如果一個對象放置在一個線程上,它將被放置在所有線程上。如果在其他線程處理它之後對它做任何事情,它應該(但不能保證)拋出一個ObjectDisposedException。

http://msdn.microsoft.com/en-us/library/system.objectdisposedexception.aspx

如果你在一個線程配置的對象,而另一個線程可期待與它的工作,你正在做的事情是錯誤的。考慮以確定性的方式控制單個線程上的對象的生命週期。

+0

如果對象在beginReceive調用中作爲「對象狀態」傳遞,那麼它也有可能是當前在sendCallback中使用的。我不確定我會如何控制你的生活時間。請參閱我的代碼示例。 – Mausimo

+1

@Mausimo對於初學者來說,你可以在每次開始做任何事情之前嘗試'lock(device){'並檢查它是否已經被處置。如果它被丟棄,不要使用它。當然,當你決定處理這個對象時,這不會幫助你處理已經掛起的呼叫。您可能只是想將其標記爲不合格,並在某些情況下稍後處理。同樣,在更改之前,你想要「鎖定(收集){'。 – 2013-02-04 20:36:38

相關問題