【发布时间】:2010-05-26 13:04:37
【问题描述】:
我目前正在做一个项目,但有点卡住了。我正在创建一个客户端服务器应用程序,它允许客户端订阅服务器以将消息转发给它。
我遇到的问题是,当客户订阅时,我希望他们只收到与他们相关的更新。系统基本上从服务器监控的 SQL 服务器 DB 传递消息。当收到一条新消息时,服务器应该只根据谁在客户端机器上登录,将该消息转发给它所应用的客户端。
我查看并找到了代码示例,这些示例注册了要在所有已订阅的客户之间广播的消息,但没有显示如何识别单个客户以及消息是否适用于他们的代码示例。
如果有人可以帮助或指出正确的方向,我将不胜感激。
edit 为了更清楚,我不是很想知道如何操作回调和订阅,而是如何操作订阅服务,当用户订阅时,他们可以在回调中提供用户 ID信息,然后可用于识别需要向哪些特定用户发送消息。
您现在可以在下面找到我的一些代码:
namespace AnnouncementServiceLibrary
{
[ServiceContract(CallbackContract = typeof(IMessageCallback))]
public interface IMessageCheck
{
[OperationContract]
void MessageCheck();
}
}
namespace AnnouncementServiceLibrary
{
public interface IMessageCallback
{
[OperationContract(IsOneWay = true)]
void OnNewMessage(Mess message);
}
}
订阅/取消订阅:
private static readonly List<IMessageCallback> subscribers = new List<IMessageCallback>();
public bool Subscribe()
{
try
{
IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
//If they dont already exist in the subscribers list, adds them to it
if (!subscribers.Contains(callback))
subscribers.Add(callback);
return true;
}
catch
{
//Otherwise if an error occurs returns false
return false;
}
}
/// <summary>
/// Unsubscribes the user from recieving new messages when they become avaliable
/// </summary>
/// <returns>Returns a bool that indicates whether the operation worked or not</returns>
public bool Unsubscribe()
{
try
{
IMessageCallback callback = OperationContext.Current.GetCallbackChannel<IMessageCallback>();
//If they exist in the list of subscribers they are then removed
if (subscribers.Contains(callback))
subscribers.Remove(callback);
return true;
}
catch
{
//Otherwise if an error occurs returns false
return false;
}
}
最后,当用户订阅时,它基本上不能正常工作,因为它循环通过我希望它根据用户的用户 ID 过滤 LINQ 查询:
#region IMessageCheck Members
/// <summary>
/// This method checks for new messages recieved based on those who have subscribed for the service
/// </summary>
public void MessageCheck()
{
//A continuous loop to keep the method going
while(true)
{
//Changes the thread to a sleep state for 2 mins?
Thread.Sleep(200000);
//Go through each subscriber based on there callback information
subscribers.ForEach(delegate(IMessageCallback callback)
{
//Checks if the person who wanted the callback can still be communicated with
if (((ICommunicationObject)callback).State == CommunicationState.Opened)
{
//Creates a link to the database and gets the required information
List<Mess> mess = new List<Mess>();
List<Message> me;
List<MessageLink> messLink;
AnnouncementDBDataContext aDb = new AnnouncementDBDataContext();
me = aDb.Messages.ToList();
messLink = aDb.MessageLinks.ToList();
//Query to retrieve any messages which are newer than the time when the last cycle finished
var result = (from a in messLink
join b in me
on a.UniqueID equals b.UniqueID
where b.TimeRecieved > _time
select new { b.UniqueID, b.Author, b.Title, b.Body, b.Priority, a.Read, b.TimeRecieved });
//Foreach result a new message is created and returned to the PC that subscribed
foreach (var a in result)
{
Mess message = new Mess(a.UniqueID, a.Author, a.Title, a.Body, a.Priority, (bool)a.Read, a.TimeRecieved);
callback.OnNewMessage(message);
}
}
//If the requesting PC can't be contacted they are removed from the subscribers list
else
{
subscribers.Remove(callback);
}
});
//Sets the datetime so the next cycle can measure against to see if new messages have been recieved
_time = DateTime.Now;
}
}
#endregion
【问题讨论】: