I have a class which has to send and receive data using sockets in Silverlight 4. It has to implement a pre-existing interface, so some things might look somewhat weird, but here it is:
public class TcpDataTransportClient : IDataTransportService
{
    private const string TCP_ADDRESS_SETTING = "tcpaddress";
    private const string TCP_PORT_SETTING = "tcpport";
    private static ManualResetEvent clientConnected = new ManualResetEvent(false);
    private static ManualResetEvent clientDataReceived = new ManualResetEvent(false);
    private static ManualResetEvent clientDataSent = new ManualResetEvent(false);
    private Dictionary<string, object> settings = new Dictionary<string, object>();
    private IDataEncapsulator dataEncapsulator;
    private IDataCollector dataCollector;
    private Socket client;
    private SocketAsyncEventArgs clientArgs;
    public event DataReceivedHandler OnDataReceived;
    public event DataSentHandler OnDataSent;
    public TcpDataTransportClient()
    {
    }
    public Dictionary<string, object> Settings
    {
        get
        {
            return this.settings;
        }
        set
        {
            this.settings = value;
        }
    }
    public IDataEncapsulator DataEncapsulator
    {
        get
        {
            return this.dataEncapsulator;
        }
        set
        {
            this.dataEncapsulator = value;
        }
    }
    public void Start(IDataCollector dataCollector)
    {
        this.dataCollector = dataCollector;
        clientArgs = new SocketAsyncEventArgs();
        client = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
        clientArgs.Completed += clientArgs_Completed;
        clientArgs.UserToken = client;            
        clientArgs.RemoteEndPoint = GetIPEndPoint();
        client.ConnectAsync(clientArgs);
        clientConnected.WaitOne();          
    }
    private IPEndPoint GetIPEndPoint()
    {
        IPAddress ipAddress;
        int tcpPort;
        if (!IPAddress.TryParse(settings[TCP_ADDRESS_SETTING].ToString(), out ipAddress))
            throw new ArgumentException(String.Format("Invalid setting for IP Address: '{0}'", TCP_ADDRESS_SETTING));
        if (!int.TryParse(settings[TCP_PORT_SETTING].ToString(), out tcpPort))
            throw new ArgumentException(String.Format("Invalid setting for TCP Port: '{0}'", TCP_PORT_SETTING));
        return new IPEndPoint(ipAddress, tcpPort);
    }
    void clientArgs_Completed(object sender, SocketAsyncEventArgs e)
    {
        switch (e.LastOperation)
        {
            case SocketAsyncOperation.Connect:
                ProcessConnect(e);
                break;
            case SocketAsyncOperation.Receive:
                ProcessReceive(e);
                break;
            case SocketAsyncOperation.Send:
                ProcessSend(e);
                break;
            default:
                throw new Exception("Invalid operation completed");
        }
    }
    private void ProcessConnect(SocketAsyncEventArgs e)
    {
        if (e.SocketError != SocketError.Success)
        {
            throw new SocketException((int)e.SocketError);
        }
        else
        {
            clientConnected.Set();
        }
    }
    private void ProcessReceive(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {
            var socket = e.UserToken as Socket;
            var response = dataCollector.Collect(e.Buffer);
            if (response != null)
            {
                if (this.OnDataReceived != null)
                    this.OnDataReceived(response);
                clientDataReceived.Set();
            }
            else
            {
                bool willRaiseEvent = socket.ReceiveAsync(clientArgs);
                if (!willRaiseEvent)
                    ProcessReceive(e);
            }
        }
        else
        {
            throw new SocketException((int)e.SocketError);
        }
    }
    private void ProcessSend(SocketAsyncEventArgs e)
    {
        if (e.SocketError == SocketError.Success)
        {                
            var socket = e.UserToken as Socket;
            if (OnDataSent != null)
                OnDataSent(clientArgs.Buffer);
            clientDataSent.Set();
            clientDataReceived.Reset();
            bool willRaiseEvent = socket.ReceiveAsync(e);
            if (!willRaiseEvent)
                ProcessReceive(e);
            clientDataReceived.WaitOne();
        }
        else
        {
            throw new SocketException((int)e.SocketError);
        }
    }
    public void Stop()
    {            
        client.Shutdown(SocketShutdown.Send);
        client.Close();
        client.Dispose();
        clientArgs.Dispose();           
    }
    public void Write(byte[] data)
    {
        clientDataSent.Reset();
        clientArgs.SetBuffer(data, 0, data.Length);
        bool willRaiseEvent = client.SendAsync(clientArgs);
        if (!willRaiseEvent)
            ProcessSend(clientArgs);
        clientDataSent.WaitOne();
    }
}
The idea here is that every request (send data) is always answered by a response (receive data), and it works fine as long as you do not disconnect and create a new connection.
For example:
client.Connect();
client.ClearConfiguration(1);
var status = client.RequestStatusDetails(1);
client.Disconnect();
This code sends multiple requests and receives an answer to each of them. However, if you run the same code again (or in a loop), the connection is established but as soon as the code reaches this point:
public void Write(byte[] data)
{
    clientDataSent.Reset();
    clientArgs.SetBuffer(data, 0, data.Length);
    bool willRaiseEvent = client.SendAsync(clientArgs);
    if (!willRaiseEvent)
        ProcessSend(clientArgs);
    clientDataSent.WaitOne();
}
An exception will be thrown for client.SendAsync(clientArgs);
This is the exception:
An asynchronous socket operation is already in progress using this SocketAsyncEventArgs instance
If however you put a breakpoint just before this statement, let VS2010 break on it, then continue debugging it works fine.
I really can't figure out what's causing this problem, and there is no additional information.
Any suggestions?