如何做长轮询正确的MVC 3 [英] How to do long polling properly in MVC 3

查看:254
本文介绍了如何做长轮询正确的MVC 3的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图线了一个AsyncController这样,当用户点击保存订单页面上的顺序,所有的用户观看相同的顺序应该得到订单已更改的通知。我要实现这种方法是做订单页面上长轮询Ajax请求,但是如何使一个可扩展的AsyncController对付这不是明摆着给我。

I am trying to wire up an AsyncController so that when a user clicks save on an order on the order page, all users viewing the same order should get a notification that the order has changed. My approach to implement this is to do long polling ajax requests on the order page, however how to make a scalable AsyncController to deal with this is not obvious to me.

所以这是我到目前为止,ID是改变或轮询更改信号通知的订单ID。

So this is what I have so far, the ID is the ID of the order that is signaled as changed or polled for changes.

public class MessageController : AsyncController
{
    static readonly ConcurrentDictionary<int, AutoResetEvent> Events = new ConcurrentDictionary<int, AutoResetEvent>();

    public ActionResult Signal(int id)
    {
        AutoResetEvent @event;
        if (Events.TryGetValue(id, out @event))
            @event.Set();

        return Content("Signal");
    }

    public void WaitAsync(int id)
    {
        Events.TryAdd(id, new AutoResetEvent(false));

        // TODO: This "works", but I should probably not block this thread.
        Events[id].WaitOne();
    }

    public ActionResult WaitCompleted()
    {
        return Content("WaitCompleted");
    }
}

我有看<一个href=\"http://stackoverflow.com/questions/1342216/how-to-do-long-polling-ajax-requests-in-asp-net-mvc\">How做在ASP.NET MVC?长轮询AJAX请求。我想了解这个code所有细节,但据我了解这code它是在线程池当中,据我了解最终将导致线程阻塞饥饿每个工作线程。

I have had a look at How to do long-polling AJAX requests in ASP.NET MVC? . I am trying to understand all details about this code but as far as I understand this code it is blocking each worker thread in the thread pool which, as far as I understand would eventually lead to thread starvation.

那么,应该怎么在一个不错的,可扩展的方式实现这一点?记住,我不希望使用任何更多的第三方组件承受,我想获得如何正确实施此方案有很好的了解。

So, how should I implement this in a nice, scalable way? Bear in mind that I do not wish to use any more third party components, I want to get a good understanding of how to implement this scenario properly.

推荐答案

其实我能够实现这个不会阻塞工作线程,我缺少的东西是ThreadPool.RegisterWaitForSingleObject。

Actually I was able to implement this without blocking the worker threads, the thing I was missing was ThreadPool.RegisterWaitForSingleObject.

public class ConcurrentLookup<TKey, TValue>
{
    private readonly Dictionary<TKey, List<TValue>> _lookup = new Dictionary<TKey, List<TValue>>();

    public void Add(TKey key, TValue value)
    {
        lock (_lookup)
        {
            if (!_lookup.ContainsKey(key))
                _lookup.Add(key, new List<TValue>());

            _lookup[key].Add(value);
        }
    }

    public List<TValue> Remove(TKey key)
    {
        lock (_lookup)
        {
            if (!_lookup.ContainsKey(key))
                return new List<TValue>();

            var values = _lookup[key];
            _lookup.Remove(key);

            return values;
        }
    }
}

[SessionState(SessionStateBehavior.Disabled)]
public class MessageController : AsyncController
{
    static readonly ConcurrentLookup<int, ManualResetEvent> Events = new ConcurrentLookup<int, ManualResetEvent>();

    public ActionResult Signal(int id)
    {
        foreach (var @event in Events.Remove(id))
            @event.Set();

        return Content("Signal " + id);
    }

    public void WaitAsync(int id)
    {
        AsyncManager.OutstandingOperations.Increment();

        var @event = new ManualResetEvent(false);

        Events.Add(id, @event);

        RegisteredWaitHandle handle = null;
        handle = ThreadPool.RegisterWaitForSingleObject(@event, (state, timeout) => 
        {
            handle.Unregister(@event);
            @event.Dispose();

            AsyncManager.Parameters["id"] = id;
            AsyncManager.Parameters["timeout"] = timeout;
            AsyncManager.OutstandingOperations.Decrement();
        }, null, new TimeSpan(0, 2, 0), false);
    }


    public ActionResult WaitCompleted(int id, bool timeout)
    {
        return Content("WaitCompleted " + id + " " + (timeout? "Timeout" : "Signaled"));
    }
}

这篇关于如何做长轮询正确的MVC 3的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆