2013-02-04 40 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

相关问题