gpt4 book ai didi

asp.net-mvc - 如何在 MVC 3 中正确进行长轮询

转载 作者:行者123 更新时间:2023-12-04 03:14:35 27 4
gpt4 key购买 nike

我正在尝试连接一个 AsyncController,以便当用户在订单页面上单击保存订单时,所有查看同一订单的用户都应该收到订单已更改的通知。我实现这个的方法是在订单页面上做长轮询ajax请求,但是如何制作一个可扩展的AsyncController来处理这个对我来说并不明显。

所以这就是我到目前为止所拥有的,ID 是指示更改或轮询更改的订单的 ID。

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");
}
}

我看过 How to do long-polling AJAX requests in ASP.NET MVC? .我试图了解有关此代码的所有详细信息,但据我了解此代码,它阻塞了线程池中的每个工作线程,据我所知,这最终会导致线程饥饿。

那么,我应该如何以一种很好的、​​可扩展的方式实现它?请记住,我不想再使用任何第三方组件,我想很好地了解如何正确实现这个场景。

最佳答案

实际上我能够在不阻塞工作线程的情况下实现这一点,我缺少的是 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"));
}
}

关于asp.net-mvc - 如何在 MVC 3 中正确进行长轮询,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/11117421/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com