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

Недавно я успешно создал сервис длинных опросов, используя HttpAsyncHandler. Во время разработки мне пришло (что), что я "мог бы" многократно использовать объект AsyncResult много раз без длительного опроса. Если возможно, я мог бы затем "смоделировать" push-технологию, перестроив или повторно использовав 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);
}

2 ответа

Решение

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

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

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

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

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

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

Удачи.

Другие вопросы по тегам