Имитация технологии push путем перестройки объекта AsynchResult - возможно ли это? - PullRequest
2 голосов
/ 07 декабря 2010

Недавно я успешно создал сервис длинных опросов, используя HttpAsyncHandler's.Во время разработки мне пришло в голову (что) я «мог бы» многократно использовать объект AsyncResult много раз без длительного опроса.Если возможно, я мог бы затем «смоделировать» push-технологию, перестроив или повторно использовав AsyncResult (обработав первый запрос как запрос на подписку).прекрасно работает, но последующие вызовы продолжают давать мне «Объект не установлен на экземпляр объекта».Я «догадываюсь», что это потому, что некоторые объекты статичны, и поэтому, «завершенный» не может быть повторно использован или извлечен (любое понимание будет УДИВИТЕЛЬНО!)1006 * Можно ли динамически построить новый обратный вызов из старого обратного вызова?

Первоначальный процесс «подписки» выглядит следующим образом:

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

Ответы [ 2 ]

4 голосов
/ 07 декабря 2010

IAsyncResult реализации должны удовлетворять определенным инвариантам , одним из которых является то, что он может быть выполнен только один раз.Вы не идентифицируете AsyncResult, который используете, но если это знаменитая версия Рихтера , то он поддержит этот инвариант.

Если вы не хотите проходить черезпроблема реализации асинхронного шаблона на основе событий , тогда лучшим вариантом будет Microsoft Rx , который является истинной системой на основе push.

0 голосов
/ 07 декабря 2010

Позвольте мне в начале предисловия сказать, что я совершенно незнаком с интерфейсом и использованием IHttpAsyncHandler.

При этом, как правило, при использовании модели асинхронного программирования каждый AsyncResult представляет определенный вызов асинхронного метода и не должен использоваться повторно. Похоже, вы ищете больше метод RegisterEvent (обратный вызов), чем метод BeginProcessing (метод обратного вызова) - поэтому даже если вы смогли заставить его работать, дизайн не будет соответствовать рекомендациям по асинхронному программированию (IMHO).

Я предполагаю, что, поскольку вы используете http, основанный на запросах / ответах, маловероятно, что вы сможете отправить несколько ответов на один запрос, и даже если вам удастся каким-то образом взломать это, ваш клиент в конечном итоге получит тайм-аут из-за его неотвеченного запроса, который может быть проблематичным для того, что вы собираетесь.

Я знаю, что в Remoting вы можете зарегистрироваться для удаленных событий, а WCF поддерживает дуплексные контракты, которые могут включать «технологию push», если это вариант для вас.

Удачи.

...