2010-12-06 32 views
2

Récemment, j'ai créé avec succès un service d'interrogation longue en utilisant HttpAsyncHandler. Au cours du développement, il m'est apparu (que) que je "pourrais" être capable de réutiliser l'objet AsyncResult plusieurs fois sans interroger à plusieurs reprises. Si possible, je pourrais alors «simuler» la technologie push en reconstruisant ou en réutilisant AsyncResult (en traitant la première requête comme s'il s'agissait d'une demande d'abonnement).Simulation de la technologie push en reconstruisant l'objet AsynchResult - est-ce encore possible?

Bien sûr, le premier appel fonctionne très bien, mais les appels suivants ne cessent de me donner "Objet non défini sur une instance d'un objet". Je "devine" c'est parce que certains objets sont statiques, et donc, une fois "terminé" ne peut pas être réutilisé ou récupéré (toute idée qu'il y aurait génial!).

La question est ...

Est-il possible de construire dynamiquement un nouveau rappel de l'ancien rappel?

Le processus "d'abonnement" initial va comme ceci:

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

Voici un exemple de ce que le service fait:

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

Voici un exemple de ce que fait l'appel 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; 
} 

SO ... SERAIT quelque chose comme ce possible?
J'ai littéralement essayé ceci et cela n'a pas fonctionné ... mais est-ce QUELQUE CHOSE "comme" c'est possible?

AsyncResult newRequest = new AsyncResult(request.cb, request.context, request.id); 

if(request.ProcessRequest(message)) 
{ 
    _subscribers.Remove(request); 
    Subscribers.Add(newRequest); 
} 

Répondre

4

IAsyncResult Les implémentations doivent satisfaire à certain invariants, dont l'une est qu'elle ne peut être remplie qu'une seule fois. Vous n'identifiez pas le AsyncResult que vous utilisez, mais si c'est Richter's famous version, alors il confirmerait cet invariant.

Si vous ne voulez pas vous donner la peine d'implémenter le event-based asynchronous pattern, alors la meilleure option est Microsoft Rx, qui est un vrai système basé sur le push.

+0

Grands commentaires! –

0

-moi d'abord préface en disant que je suis tout à fait familier avec l'interface IHttpAsyncHandler et de l'utilisation. Cela étant dit, en général, lors de l'utilisation d'un modèle de programmation asynchrone, chaque AsyncResult représente un appel de méthode asynchrone spécifique et ne doit pas être réutilisé. On dirait que vous recherchez plus une méthode RegisterEvent (callback) qu'un BeginProcessing (méthode de rappel) - même si vous étiez en mesure de faire fonctionner cela, la conception ne tient pas par les meilleures pratiques de programmation asynchrones (IMHO). Je suppose que puisque vous utilisez http qui est basé sur la requête/réponse, il semble improbable que vous puissiez pousser plusieurs réponses pour une requête et même si vous avez réussi à le pirater, votre client finira par obtenir un délai d'attente en raison de sa demande sans réponse ce qui serait problématique pour ce que vous allez. Je sais que dans Remoting, vous pouvez vous inscrire pour des événements à distance et WCF prend en charge les contrats duplex qui peuvent activer la "technologie push" si c'est une option pour vous.

Bonne chance.

+0

Merci beaucoup! –