2

最近,我使用 HttpAsyncHandler 成功创建了一个长轮询服务。在开发过程中,我想到(我)“可能”能够多次重用 AsyncResult 对象,而无需反复进行长轮询。如果可能的话,我可以通过以某种方式重新构建或重新使用 AsyncResult 来“模拟”推送技术(将第一个请求视为订阅请求)。

当然,第一次调用效果很好,但随后的调用不断给我“对象未设置为对象的实例”。我“猜测”是因为某些对象是静态的,因此,一旦“完成”就无法重用或检索(任何洞察力都会很棒!)。

所以问题是……</p>

是否可以从旧回调动态构建新回调?

最初的“订阅”过程如下:

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

2 回答 2

4

IAsyncResult实现必须满足某些不变量,其中之一是它只能完成一次。您无法识别AsyncResult您正在使用的版本,但如果它是Richter 的著名版本,那么它将支持该不变量。

如果您不想为实现基于事件的异步模式而烦恼,那么最好的选择是Microsoft Rx,它是一个真正的基于推送的系统。

于 2010-12-07T04:00:00.280 回答
0

我先说我对 IHttpAsyncHandler 接口和用法完全不熟悉。

话虽如此,通常在使用异步编程模型时,每个 AsyncResult 代表一个特定的异步方法调用,不应重用。似乎您正在寻找 RegisterEvent(callback) 方法而不是 BeginProcessing(callback 方法) - 因此,即使您能够使其工作,该设计也不符合异步编程最佳实践 (IMHO)。

我假设由于您使用的是基于请求/响应的 http,您似乎不太可能为一个请求推送多个响应,即使您能够以某种方式破解它,您的客户端最终也会因超时而超时对其未答复的请求,这对于您的目标将是有问题的。

我知道在 Remoting 中您可以注册远程事件,并且 WCF 支持双工合同,如果这是您的一个选项,则可以启用“推送技术”。

祝你好运。

于 2010-12-06T22:32:21.490 回答