Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/257.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# WCF发布/订阅并使用回调向特定用户发送数据_C#_Wcf_Callback - Fatal编程技术网

C# WCF发布/订阅并使用回调向特定用户发送数据

C# WCF发布/订阅并使用回调向特定用户发送数据,c#,wcf,callback,C#,Wcf,Callback,我现在正在做一个项目,有点卡住了。我正在创建一个客户端-服务器应用程序,它允许客户端订阅服务器,并将消息转发给服务器 我遇到的问题是,当客户端订阅时,我希望他们只接收与之相关的更新。系统基本上从服务器监视的SQL server DB传递消息。当接收到新消息时,服务器只应根据登录到客户端计算机的用户将消息转发给其应用的客户端 我查看了一下,发现了一些代码示例,这些示例注册了要在所有已订阅的客户端上广播的消息,但没有任何示例显示如何识别单个客户端以及消息是否适用于这些客户端 如果有人能帮我或给我指出

我现在正在做一个项目,有点卡住了。我正在创建一个客户端-服务器应用程序,它允许客户端订阅服务器,并将消息转发给服务器

我遇到的问题是,当客户端订阅时,我希望他们只接收与之相关的更新。系统基本上从服务器监视的SQL server DB传递消息。当接收到新消息时,服务器只应根据登录到客户端计算机的用户将消息转发给其应用的客户端

我查看了一下,发现了一些代码示例,这些示例注册了要在所有已订阅的客户端上广播的消息,但没有任何示例显示如何识别单个客户端以及消息是否适用于这些客户端

如果有人能帮我或给我指出正确的方向,我将不胜感激

编辑只是为了更清楚,我不太想知道如何操作回调和订阅,而是想知道如何操作订阅服务,当用户订阅时,他们可以在那里提供用户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;
        }

    }
private static readonly List subscribers=new List();
公共bool Subscribe()
{
尝试
{
IMessageCallback callback=OperationContext.Current.GetCallbackChannel();
//如果订阅者列表中不存在,则将其添加到订阅者列表中
如果(!subscribers.Contains(回调))
添加(回调);
返回true;
}
抓住
{
//否则,如果发生错误,则返回false
返回false;
}
}
/// 
///当新消息可用时,取消用户接收新消息的订阅
/// 
///返回一个bool,指示操作是否有效
公共bool退订()
{
尝试
{
IMessageCallback callback=OperationContext.Current.GetCallbackChannel();
//如果订阅服务器列表中存在,则会将其删除
if(subscribers.Contains(回调))
删除(回调);
返回true;
}
抓住
{
//否则,如果发生错误,则返回false
返回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
#区域IMessageCheck成员
/// 
///此方法根据已订阅服务的用户检查接收到的新消息
/// 
public void MessageCheck()
{
//保持方法运行的连续循环
while(true)
{
//将线程更改为睡眠状态2分钟?
睡眠(20万);
//根据这些回调信息检查每个订阅者
ForEach(委托(IMessageCallback)
{
//检查是否仍然可以与想要回拨的人通信
if(((ICommunicationObject)回调).State==CommunicationState.Opened)
{
//创建到数据库的链接并获取所需信息
List mess=新列表();
列出我;
列表链接;
AnnouncementDBDataContext aDb=新的AnnouncementDBDataContext();
me=aDb.Messages.ToList();
messLink=aDb.MessageLinks.ToList();
//查询以检索比上一个周期完成时更新的任何消息
var结果=(来自messLink中的
加入我
关于a.UniqueID等于b.UniqueID
其中b.timereceived>\u时间
选择new{b.UniqueID,b.Author,b.Title,b.Body,b.Priority,a.Read,b.timereceived});
//对于每个结果,将创建一条新消息并返回给订阅的PC
foreach(结果中的var a)
{
Mess消息=新Mess(a.UniqueID,a.Author,a.Title,a.Body,a.Priority,(bool)a.Read,a.timereceived);
callback.OnNewMessage(消息);
}
}
//如果无法联系到请求的PC,则会将其从订户列表中删除
其他的
{
删除(回调);
}
});
//设置日期时间,以便下一个周期可以测量以查看是否接收到新消息
_时间=日期时间。现在;
}
}
#端区

您可以使用双工通道。为此,必须提供同时支持会话通信和双工通信的绑定。然后,客户机必须传递一个由CallbackHandler实例构造的InstanceContext。最后,服务器将使用以下命令获取上下文(用于回调消息):


请看一下Juval Lowy的发布-订阅WCF框架,该框架在中有相当详细的描述。代码可以通过文章查看,也可以从Lowy的网站下载源代码和示例。转到下载部分,按发现类别进行筛选,您将在那里看到它

我在我的WCF应用程序中使用这个机制,它
OperationContext.Current.GetCallbackChannel<ICallBackServiceContract>();
[ServiceBehavior(InstanceContextMode=InstanceContextMode.PerSession)]
class Subscriber
{
    public string UserName { get; set; }
    public IMessageCallback CallBack { get; set; }
}