views:

120

answers:

3
+1  Q: 

Odd WCF problem

I have a server-client using WCF.

The server has a list of clients.

To check for timeouts, every minute it sends a bit of data (ping) to each client. All sending is done asynchronously - so the line looks like this:

for (int i = 0; i < MaxUsers; i++)
{
    if (_clients[i] != null)
    {
        _clients[i].Client.BeginSendToClient("PING", new AsyncCallback(this.SendToClientCallback), _clients[i].Client);

Now the SentToClientCallback method starts off like this:

void SendToClientCallback(IAsyncResult asyncResult)
{
    IClientAsync callback = null;
    try
    {
        callback = (IClientAsync)asyncResult.AsyncState;
        callback.EndSendToClient(asyncResult);
    }
    catch (TimeoutException e)

The timeout exception has to convert the result we sent back to get the index of the client in our _client array... and it does so using a method I wrote:

int myClientIndex = GetClientIndexFromCallback(CurrentCallback);

where

private int GetClientIndexFromCallback(IClientAsync callback)
{

    for (int i = 0; i < MaxUsers; i++)
    {
        if (_clients[i] != null && _clients[i].Client.Equals(callback))
        {
            // found
            return i;

Now this code works fine if I connect, then disconnect. It sends the PING, goes to the callback method. It generates a timeout exception. It gets the id number (which is 0) and removes _client[0] and all is good.

However, if I connect and disconnect twice in a row, before the first connect timed out, only one of the connections (the second one, or _client[1]) disconnects. The other one remains, and constantly gets sent PING. The callback method keeps running, and keeps generating a timeout exception... but when I call my method to get the id of it, it cannot find it. For some reason, _clients[i].Client.Equals(callback) is not returning true.

How is this possible? Every PING command sends _clients[0].Client, but when I go to compare it in my method, it returns false.

A: 

it seems you access _clients from multiple threads. List<T> is not thread safe. This would explain this weird behavior.

Nicolas Dorier
I am not using a List, just an array. I don't see how threads would affect it, multiple threads can access each others objects without problems usually, plus I have a lock in place to ensure no thread-unsafe activities occur.
Simon
you said "removes _client[0]" but we cannot remove something of an array, that's why I thought you used a list
Nicolas Dorier
A: 

Just curious but why do you start with an index into an array, send in the WCF proxy object and then start searching for its index again in the array. Seems much simpler and saver to send in the index as the AsyncState and your problems are gone.

Maurice
A: 

How is Equals implemented for IClientAsync?

Also I agree with Slashene that it could be related to threads. The Async callbacks are going to be coming in on different threads. Each of these is working on the same array, one of the threads could be "removing" an element from the array while the other is half way through iterating through it.

Where does the value for MaxUsers come from? is this the total number of connected users?

Shiraz Bhaiji