ASP.net如何用PokeIn进行长时间轮询?

时间:2012-06-26 15:39:16

标签: asp.net comet pokein

我想提供一个服务,以便在发送给他的新消息时通知用户。因此,我想使用一些提供服务器推送能力的Comet框架。所以我调查了PokeIn

只是想知道一件事。我查看了他们在网站上的样本。如果有的话,他们都不会查看数据库以检索新条目。但我想这只是一个修改问题。

其中一个示例通过在服务器端使用sleep来实现此长轮询。因此,如果我使用相同的方法,我可以检查数据库,如果有任何新条目,则每5秒。然而,这种方法似乎与使用javascript在客户端使用轮询时没有太大的不同。

这部分来自一个样本。可以看出,他们在那里睡觉,以更新每个人的当前时间。

static void UpdateClients()
    {
        while (true)
        {
            //.. code to check database 
            if (CometWorker.ActiveClientCount > 0)
            {
                CometWorker.SendToAll(JSON.Method("UpdateTime", DateTime.Now));
            }
            Thread.Sleep(500);
        }
    }

所以我想知道我应该如何实现消息通知器?似乎上述方法仍然会在服务器端推动巨大的负载需求。消息通知器打算与发现Facebook的方式相同。

2 个答案:

答案 0 :(得分:2)

你不应该以这种方式实现,该样本只是这样实现的,因为保持PokeIn相关部分是清楚的。您应该按照提到的那样实现SQL部分http://www.codeproject.com/Articles/12335/Using-SqlDependency-for-data-change-events 为了跟踪数据库的变化。

因此,当您要发送内容时,请调用其中一个PokeIn方法进行客户端交付。我不知道,你的应用程序对时间要求多少很重要,因为除了反向ajax之外,PokeIn的内部websocket功能非常容易激活,并且可以非常快速地向客户端发送消息。

答案 1 :(得分:0)

你可以用@Zuuum说的那样用数据库来做,但是我用不同的方式实现了它。

我在Windows Azure环境中使用带有PokeIn和EF的ASP.NET MVC:

  • 我的域事件与此方法类似:Strengthening your domain: Domain Events
  • 当有人调用某个操作时,这是Unit of Work
  • 如果UOW成功,那么我举起一个域事件(例如 ChatMessageSent
  • 我有这些域事件的订阅者,因此他们可以接收事件并将消息转发给PokeIn侦听器

我将这种模式用于游戏网站上的所有实时需求(在游戏中进行移动,操作等),我不想在这里做广告,如果你愿意,你可以通过我找到它。 / p>

我总是将此模式用作双工通信解决方案,因此每个人都可以通过PokeIn获取更新,甚至是调用操作的用户,因此每个客户端的行为都相同。因此,当某人调用某个动作时,除了成功信号之外,它不会返回任何内容。

接下来的示例将不起作用,因为它们只是用于演示流程的片段

以下是我的代码中的操作代码段:

[HttpPost]
[UnitOfWork]
[RestrictToAjax]
[ValidateAntiForgeryToken]
public JsonResult Post(SendMessageViewModel msg) 
{ 
    if (ModelState.IsValid)
    {
        var chatMessage = new ChatMessage
        {
            ContainerType = msg.ContainerType,
            ContainerID = msg.ContainerID,
            Message = _xssEncoder.Encode(msg.Message),
            User = _profileService.CurrentUser
        };

        _chatRepository.AddMessage(chatMessage);
        OnSuccessfulUoW = () => EventBroker.Current.Send(this, new ChatMessageSentPayload(chatMessage));
    }

    return Json(Constants.AjaxOk);
}

和(简化的)EventBroker实现:

public class UnityEventBroker : EventBroker
{
    private readonly IUnityContainer _container;

    public UnityEventBroker(IUnityContainer container)
    {
        _container = container;
    }

    public override void Send<TPayload>(object sender, TPayload payload)
    {
        var subscribers = _container.ResolveAll<IEventSubscriber<TPayload>>();
        if (subscribers == null) return;
        foreach (var subscriber in subscribers)
        {
            subscriber.Receive(sender, payload);
        }
    }
}

更简化的订户:

public class ChatMessageSentSubscriber : IEventSubscriber<ChatMessageSentPayload>
{
    public void Receive(object sender, ChatMessageSentPayload payload)
    {
        var message = payload.Message;
        var content = SiteContent.Global;

        var clients = Client.GetClients(c => c.ContentID == message.ContainerID && c.Content == content)
                            .Select(c => c.ClientID)
                            .ToArray();

        var dto = ObjectMapper.Current.Map<ChatMessage, ChatMessageSentDto>(message);

        var json = PokeIn.JSON.Method("pokein", dto);
        CometWorker.SendToClients(clients, json);
    }
}