2016-12-07 1 views
5

J'ai un projet C# ASP.Net (non MVC) qui utilise l'interrogation longue Ajax Comet. Une page Web effectue un appel HTTP à un point de terminaison géré par une classe implémentant IHttpAsyncHandler.Comment faire C# Ajax Comet via WebAPI2?

S'il n'y a rien à signaler (en l'espace de n secondes) à la page Web, une réponse HTTP vide est envoyée et la page Web est rappelée. S'il y a quelque chose à envoyer, et la mise à jour est envoyée, et la page Web traite et re-appelle. C'est une technologie poussée assez standard, et fonctionne très bien.

Maintenant, j'essaie d'ajouter des points de terminaison API, en utilisant WebAPI2, non-MVC. J'ai des contrôleurs synchrones qui fonctionnent, basés sur la classe ApiController.

Je souhaite configurer la technologie Push pour les appels d'API, afin que les utilisateurs de l'API n'aient pas besoin de rechercher des mises à jour.

Similaire à la méthode ci-dessus, l'appel de l'extrémité API est reçu et le contexte est stocké. Si un délai expire, l'appel est renvoyé vide et l'appelant est appelé à rappeler. Si les données sont mises à jour dans le délai imparti, les données sont renvoyées à l'appelant et l'appelant est alors appelé à appeler à nouveau et à attendre d'autres mises à jour.

Le problème est qu'il ne semble pas y avoir de version asynchrone d'ApiController. Le but est de libérer le thread qui gère l'appel de l'API, de le renvoyer au pool, puis, lorsque des données sont disponibles, ou que le délai expire, un thread de travail est utilisé pour renvoyer la réponse.

Comment puis-je configurer un ApiController afin que le thread traitant l'appel soit libéré, que le contexte d'appel soit stocké et que je puisse envoyer une réponse à l'appel plus tard?

+1

Pourquoi n'utilisez-vous pas SignalR? –

+0

De longs travaux de sondage et est très efficace, spécialement pour les connexions de mauvaise qualité. Cela fonctionne bien. J'ai juste besoin de comprendre comment raccrocher une connexion WebAPI2 comme s'il s'agissait d'une requête HTTP standard. –

Répondre

2

Vous pouvez utiliser async/vous attendent pour obtenir ce que vous voulez savoir:

[HttpPost] 
public async Task<HttpResponseMessage> LongRunningOperation([FromBody]Input obj) 
{ 
    // Do what ever you need with input data   

    await WaitForEvent();   

    // Do what ever you need to return a response 

    return someResponse; 
} 

Dans cet exemple, la méthode de l'API Web est déclarée comme async et dans son corps await opérateur a été utilisé pour retourner un fil à une piscine . J'ai supposé que pour implémenter Comet vous utilisez un certain type d'événements. Pour autant que je me souvienne de nombreuses années, j'ai utilisé ManualResetEvent pour le faire. Cependant, cela peut être autre chose.

Ce qui est important est que la méthode WaitForEvent devrait retourner quelque chose d'attendu. En d'autres termes ManualResetEvent ou un autre handle d'attente doit être enveloppé dans une tâche. Vous pouvez le faire avec la méthode AsyncFactory.FromWaitHandle.

Il est également intéressant de lire ce discussion à propos de asyn/await dans le contexte de l'API Web.

+0

J'utilise des événements ailleurs, pour des querelles de threads normales, mais je n'avais pas pensé à les utiliser ici. Je vais essayer, merci pour le poste. –

+0

Pour la comète de site Web, actuellement j'utilise des gestionnaires async Http. Il crée un objet AsyncResult dérivé qui enveloppe le contexte http. Les objets AsyncResult sont stockés dans une collection jusqu'à ce que le délai expire ou que les données arrivent. Lorsque l'une ou l'autre se produit, la demande de contexte est terminée. Le client rencontre soit une réponse vide au moment de l'expiration, soit une réponse avec des données à un certain moment avant le délai d'expiration (par exemple, la comète classique), et dans les deux cas, des boucles client et des re-demandes. Le client est presque toujours connecté, attendant passivement des données, sans attacher un fil. –