Click here to Skip to main content
15,883,705 members
Please Sign up or sign in to vote.
0.00/5 (No votes)
See more:
After starting the WCF service on the server, I connect two different Clients to the server. After a while, both Clients lose the connection with the server. It is because of any issue such as the network adapter crash. After that, Server try to call the callback function but the server does not know this Client is not existing anymore to respond the request. Therefore, it is cause a deadlock.
Does anyone know how to prevent this issue???


C#
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single,
ConcurrencyMode = ConcurrencyMode.Multiple, UseSynchronizationContext = false)]
public class ChatService : IChat
{
    Dictionary<Client, IChatCallback> clients = new Dictionary<Client, IChatCallback>();

    List<Client> clientList = new List<Client>();

    public IChatCallback CurrentCallback
    {
        get
        {
            return OperationContext.Current.GetCallbackChannel<IChatCallback>();

        }
    }

    object syncObj = new object();

    private bool SearchClientsByName(string name)
    {
        foreach (Client c in clients.Keys)
        {
            if (c.Name == name)
            {
                return true;
            }
        }
        return false;
    }

    #region IServices Members
    // Public client connection 
    // retern true, when the connection has been established successfully
    // otherwise return false 
    public bool Connect(Client client)
    {
        lock (syncObj)
        {
            // Remove the client if it exists
            RemoveSubscriberByKey(client);

            // Add client with the callback
            AddSubscriber(client);

            OperationContext.Current.Channel.Faulted += new EventHandler(Channel_Faulted);
            OperationContext.Current.Channel.Closed += new EventHandler(Channel_Closed);

            foreach (IChatCallback callback in clients.Values)
            {
                try
                {
                    if (((ICommunicationObject)callback).State == CommunicationState.Opened)
                    {
                        // State is still opened, but actully is not
                        CallMethod(() => callback.RefreshClients(clientList));
                        CallMethod(() => callback.UserJoin(client));
                    }
                    else
                    {
                        RemoveSubscriberByValue(callback);
                    }
                }
                catch
                {
                    RemoveSubscriberByValue(callback);
                    return false;
                }
            }
        }
        return true;
    }

    private void AddSubscriber(Client client)
    {
        clients.Add(client, CurrentCallback);
        clientList.Add(client);
    }

    private void RemoveSubscriber(Client client)
    {
        clients.Remove(client);
        clientList.Remove(client);
    }

    private void RemoveSubscriberByKey(Client client)
    {
        if (clients.Count > 0)
        {
            foreach (var item in clients.Keys.Where(item => item.Name.Equals(client.Name)))
            {
                clients.Remove(client);
                clientList.Remove(client);
            }
        }
    }

    private void RemoveSubscriberByValue(IChatCallback callback)
    {
        if(clients.Values.Contains(callback))
        {
            Client c = clients.FirstOrDefault(x => x.Value == callback).Key;
            clients.Remove(c);
            clientList.Remove(c);
        }
    }

    void Channel_Closed(object sender, EventArgs e)
    {
        IChatCallback machine = sender as IChatCallback;
        RemoveSubscriberByValue(machine);
    }

    void Channel_Faulted(object sender, EventArgs e)
    {
        IChatCallback machine = sender as IChatCallback;
        RemoveSubscriberByValue(machine);
    }

    public void CallMethod(Action methodToBeCalled)
    {
        try
        {
            methodToBeCalled();
        }
        catch (TimeoutException ex)
        {
        }
        catch (CommunicationException ex)
        {
        }
        catch (ObjectDisposedException ex)
        {
        }
        catch (Exception ex)
        {
        }
    }
}
Posted
Updated 14-May-14 21:52pm
v2

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900