2010-12-06 3 views
2

Недавно я успешно создал службу долгосрочного опроса с использованием HttpAsyncHandler. Во время разработки мне пришло в голову (что) я могу «повторно использовать объект AsyncResult много раз без повторного опроса. Если возможно, я мог бы затем «имитировать» push-технологию путем перестройки или повторного использования AsyncResult каким-то образом (обработка первого запроса, как если бы это был запрос на подписку).Имитация технологии push путем восстановления объекта AsynchResult - возможно ли это?

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

Таким образом, вопрос ...

Можно ли построить динамически новую функцию обратного вызова от старого обратного вызова?

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

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

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

Если вы не хотите выполнять проблему с использованием event-based asynchronous pattern, то лучшим вариантом является Microsoft Rx, что является настоящей системой на основе push.

+0

Отличные комментарии! – 2010-12-07 12:16:10

0

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

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

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

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

Удачи.

+0

Большое вам спасибо! – 2010-12-07 12:17:06