通过重建 AsynchResult 对象来模拟推送技术 - 这可能吗?
最近,我使用 HttpAsyncHandler 成功创建了一个长轮询服务。在开发过程中,我意识到我“可能”能够多次重复使用 AsyncResult 对象,而无需重复进行长轮询。如果可能的话,我可以通过以某种方式重新构建或重新使用 AsyncResult 来“模拟”推送技术(将第一个请求视为订阅请求)。
当然,第一次调用效果很好,但后续调用不断给出“对象未设置为对象的实例”。我“猜测”这是因为某些对象是静态的,因此一旦“完成”就无法重用或检索(任何见解都很棒!)。
所以问题是……
是否可以从旧回调动态构建新回调?
最初的“订阅”过程如下:
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
Guid id = new Guid(context.Request["Key"]);
AsyncResult request = new AsyncResult(cb, context, id);
Service.Singleton.Subscribe(request);
return request;
}
以下是该服务的功能示例:
private void MainLoop()
{
while (true)
{
if (_subscribers.Count == 0)
{
if (_messages.Count == max)
_messages.Clear();
}
else
{
if (_messages.Count > 0)
{
Message message = _messages.Dequeue();
foreach (AsyncResult request in _subscribers.ToArray())
{
if(request.ProcessRequest(message));
_subscribers.Remove(request);
}
}
}
Thread.Sleep(500);
}
}
以下是该服务的功能示例 : AsyncResult.ProcessRequest() 调用会执行以下操作:
public bool ProcessRequest(Message message)
{
try
{
this.Response = DoSomethingUseful(message);
this.Response.SessionValid = true;
}
catch (Exception ex)
{
this.Response = new Response();
this.Response.SessionValid = false;
}
this.IsCompleted = true;
_asyncCallback(this);
return this.IsCompleted;
}
那么...这样的事情可能吗?
我确实尝试过这个,但它不起作用......但是“类似”的东西可能吗?
AsyncResult newRequest = new AsyncResult(request.cb, request.context, request.id);
if(request.ProcessRequest(message))
{
_subscribers.Remove(request);
Subscribers.Add(newRequest);
}
Recently, I successfully created a long-polling service using HttpAsyncHandler’s. During the development it came to me (that) I “might” be able to re-use the AsyncResult object many times without long-polling repeatedly. If possible, I could then “simulate” push-technology by re-building or re-using the AsyncResult somehow (treating the first request as though it were a subscription-request).
Of course, the first call works great, but subsequent calls keep giving me “Object not set to an instance of an object”. I am “guessing” it is because certain objects are static, and therefore, once "completed" cannot be reused or retrieved (any insight there would be AWESOME!).
So the question is…
Is it possible to build dynamically a new callback from the old callback?
The initial "subscription" process goes like this:
public IAsyncResult BeginProcessRequest(HttpContext context, AsyncCallback cb, object extraData)
{
Guid id = new Guid(context.Request["Key"]);
AsyncResult request = new AsyncResult(cb, context, id);
Service.Singleton.Subscribe(request);
return request;
}
Here is an example of what the service does:
private void MainLoop()
{
while (true)
{
if (_subscribers.Count == 0)
{
if (_messages.Count == max)
_messages.Clear();
}
else
{
if (_messages.Count > 0)
{
Message message = _messages.Dequeue();
foreach (AsyncResult request in _subscribers.ToArray())
{
if(request.ProcessRequest(message));
_subscribers.Remove(request);
}
}
}
Thread.Sleep(500);
}
}
Here is an example of what the AsyncResult.ProcessRequest() call does:
public bool ProcessRequest(Message message)
{
try
{
this.Response = DoSomethingUseful(message);
this.Response.SessionValid = true;
}
catch (Exception ex)
{
this.Response = new Response();
this.Response.SessionValid = false;
}
this.IsCompleted = true;
_asyncCallback(this);
return this.IsCompleted;
}
SO...WOULD SOMETHING LIKE THIS BE POSSIBLE?
I literally tried this and it didn't work...but is SOMETHING "like" it possible?
AsyncResult newRequest = new AsyncResult(request.cb, request.context, request.id);
if(request.ProcessRequest(message))
{
_subscribers.Remove(request);
Subscribers.Add(newRequest);
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
IAsyncResult
实现必须满足某些不变量,其中之一就是只能完成一次。您无法识别正在使用的AsyncResult
,但如果它是 Richter 的著名版本,那么它将维持这个不变量。如果您不想经历实现基于事件的异步模式的麻烦,那么最好的选择是 Microsoft Rx,即真正的基于推送的系统。
IAsyncResult
implementations must satisfy certain invariants, one of which is that it can only be completed once. You don't identify theAsyncResult
you're using, but if it's Richter's famous version, then it would uphold that invariant.If you don't want to go through the trouble of implementing the event-based asynchronous pattern, then the best option is Microsoft Rx, which is a true push-based system.
首先我要说的是我完全不熟悉 IHttpAsyncHandler 接口和用法。
话虽这么说,通常在使用异步编程模型时,每个 AsyncResult 都代表一个特定的异步方法调用,不应重用。似乎您更多地寻找 RegisterEvent(callback) 方法而不是 BeginProcessing(callback method) - 所以即使您能够让它工作,该设计也不符合异步编程最佳实践(恕我直言)。
我假设由于您使用的是基于请求/响应的http,因此您似乎不太可能为一个请求推送多个响应,即使您能够以某种方式解决这个问题,您的客户端最终也会因超时而超时对其未答复的请求,这对您的目的来说将是有问题的。
我知道在远程处理中,您可以注册远程事件,并且 WCF 支持双工合约,如果您可以选择,它可以启用“推送技术”。
祝你好运。
Let me first preface by saying I am completely unfamiliar with IHttpAsyncHandler interface and usage.
That being said, in general when using an asynchronous programming model, each AsyncResult represents a specific asynchronous method call and should not be reused. Seems like you are looking more for a RegisterEvent(callback) method than a BeginProcessing(callback method) - so even if you were able to get this to work, the design does not hold by asynchonous programming best practices (IMHO).
I assume that since you are using http which is request/response based, it seems unlikely that you will be able to push multiple responses for one request and even if you were able to somehow hack this up, your client will eventually get a timeout due to its unanswered request which would be problematic for what you are going for.
I know in Remoting you can register for remote events and WCF supports duplex contracts which can enable "push technology" if this is an option for you.
Good luck.