但是我遇到了与客户端实现的回调相关的问题。当客户端点击断开连接按钮时,它运行良好,但万一,客户端因为断开网络,计算机关闭等原因而崩溃,之后服务无法正常工作。看来服务也会出错。
[ServiceContract(CallbackContract = typeof(IChatCallback), SessionMode = SessionMode.Required)]
public interface IChat
{
[OperationContract(IsInitiating = true)]
bool Connect(Client client);
[OperationContract(IsOneWay = true)]
void Say(Message msg);
[OperationContract(IsOneWay = true)]
void Whisper(Message msg, Client receiver);
[OperationContract(IsOneWay = true)]
void OperSelectClient(Client oper, string client, bool connect, bool isdisconnect);
[OperationContract(IsOneWay = true)]
void IsWriting(Client client);
[OperationContract(IsOneWay = true, IsTerminating = true)]
void Disconnect(Client client);
[OperationContract(IsOneWay = true)]
void OperatorsUpdate();
[OperationContract(IsOneWay = true)]
void RefreshClientsAndOperators(Client client);
}
public interface IChatCallback
{
[OperationContract(IsOneWay = true)]
void RefreshClients(List<Client> clients);
[OperationContract(IsOneWay = true)]
void Receive(Message msg);
[OperationContract(IsOneWay = true)]
void ReceiveWhisper(Message msg, Client receiver);
[OperationContract(IsOneWay = true)]
void ClientSelect(Client oper, string client);
[OperationContract(IsOneWay = true)]
void IsWritingCallback(Client client);
[OperationContract(IsOneWay = true)]
void UserJoin(Client client);
[OperationContract(IsOneWay = true)]
void UserLeave(Client client);
}
[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();
public bool Connect(Client client)
{
if (SearchClientsByName(client.Name) && !clients.ContainsValue(CurrentCallback))
{
OperationContext.Current.Channel.Faulted += new EventHandler(delegate { Disconnect(client); });
OperationContext.Current.Channel.Closed += new EventHandler(delegate { Disconnect(client); });
lock (syncObj)
{
clients.Add(client, CurrentCallback);
clientList.Add(client);
foreach (Client key in clients.Keys)
{
IChatCallback callback = clients[key];
try
{
callback.RefreshClients(clientList);
callback.UserJoin(client);
}
catch
{
clients.Remove(key);
return false;
}
}
}
}}