J'ai une application Lorsque quelqu'un envoie une demande à lorsque le La tâche consiste à attendre une requête postale à l'intérieur L'exemple ci-dessous pourrait aider à clarifier le problème: P> localApp code> avec un contrôleur API-contrôleur
myController_a code>.
MyController_a code>, le contrôleur redirige La demande à une application différente
RemoteApp code> et pause. p>
remoteApp code> a effectué avec des calculs, il envoie une demande postale au
localApp code>, à un autre contrôleur
mycontroller_b code>. p>
mycontroller_a code> à partir du
mycontroller_b Code> Avant d'envoyer une réponse. P>
public class MyController_A : ControllerBase
{
public object Post([FromBody] MyModel message)
{
SendDataToAnotherApp(message);
object result = new Task<object>(() =>
{
// Listening requests to MyController_B
return request;
}).Result;
return result;
}
}
3 Réponses :
Vous pouvez utiliser async / attendre pour votre contrôleur A
public class MyController_A : ControllerBase { public async Task<object> Post([FromBody] MyModel message) { return await SendDataToAnotherApp(message); } }
Non, cela ne répond pas à ma question.
OP est de demander comment il peut attendre (A / Index) si la réponse se présente à différentes actions de contrôleur (B / Index).
Si vous dites de contrôler.index (), vous appelez contrôleur.index (). C'est juste faux et ne fais pas ça. Au lieu de cela, créez un service (Commonervice.cs) et injectez-le dans les deux contrôleurs.
@ Alex-TNILE, merci de réponse. Je le ferai plus tard, dès que je découvrirai, comment attraper l'autre demande
Peut-être que vous devriez vous redéfinir l'architecture et ne pas garder votre contrôleur actif en attente de l'autre appel de retour. p>
Gardez à l'esprit que les demandes HTTP ont une durée limitée et une fois qu'ils ferment, les fils à l'intérieur mourront. p>
Je ne sais pas si c'est idéal pour votre occasion, mais je recommanderais d'utiliser SignalR pour envoyer les données à votre client via des sockets Web lorsque le deuxième contrôleur a terminé le travail. P>
Merci de répondre. Le problème n'est que le RemoteApp. Son architecture restreint fortement mes possibilités :)
Mais je vais essayer de le redéfinir avec Signalr!
:) Je suis sûr que vous serez très satisfait: D
donc, peut-être pas la meilleure solution, mais cela fonctionne.
J'ai sauvegardé la demande au mycontroller_b code> à l'intérieur du httpcontext.session et obtenez sa valeur à partir de
MyController_a Code> . P>
public class MyController_B : ControllerBase {
public void Post([FromBody] string message)
{
HttpContext.Session.SetString("MyController_B_request", message);
}
}
public class MyController_A : ControllerBase
{
public object Post([FromBody] MyModel message)
{
SendDataToAnotherApp(message);
object result = new Task<object>(() =>
{
string request;
while (true)
{
request = HttpContext.Session.GetString("MyController_B_request");
if (!string.IsNullOrEmpty(request))
break;
Task.Delay(1000).Wait();
}
return request;
}).Result;
return result;
}
}
Quel est le point de se débarrasser d'une tâche et d'y attendre de manière bloquante? En outre, c'est une jolie ... mauvaise façon faire des choses. Si l'utilisateur exécute deux demandes, vous n'avez aucune idée de laquelle on sera à l'intérieur de la session
Ou si c'est une application Web (même si ce n'est pas que dans votre contrôle, vous pouvez utiliser le client C # SingAlr C # sur l'application faisant le premier appel), terminez la première demande après appelant externe et utilisez Signalr pour notifier au navigateur que l'opération a été terminée. Donc, votre application Web peut initier une 2ème demande pour obtenir le résultat plutôt que de bloquer la connexion tout le temps.
@Tseng, merci pour votre commentaire! La tâche de blocage n'est pas pour une utilisation réelle. C'était en fait une méthode distincte, mais pour rendre le post plus compact, je l'emballe dans une tâche.
Je n'ai pas utilisé Signalr auparavant, mais sonne comme une bonne chose. Je vais l'essayer!
Démarrer une tâche et l'attendre (de manière bloquante) n'a toujours aucun sens. Qu'attendez-vous que cela fasse? Vous bloquez efficacement Deux threads B>, au lieu d'un si vous auriez simplement la boucle tandis que la méthode d'action (aucune tâche ou fil du tout). Et comme je l'ai dit, sur la concurrence (plusieurs demandes du même utilisateur) son dangereux
@Tseng, maintenant je comprends ce que tu veux dire :( Je dois apprendre toutes ces choses. Merci d'avoir clarifié.
Également sur le dessus si cela, votre code peut incroyablement travailler, avez-vous même testé dans un scénario réaliste? Lorsque myController_B code> est appelé, son appelé par le serveur distant, il n'y a donc pas de cookie de session. Les sessions sont spécifiques à l'utilisateur et le code distant écrirait à une session "Sans nom" et qu'elle n'apparaîtrait jamais dans la session d'utilisateurs en premier lieu et votre code à partir de
myController_a code> ne terminerait jamais
Eh bien, pas spécifique de l'utilisateur b> mais demande spécifique b> et identifié par une clé unique fournie dans le cookie de session à être plus spécifique. Point est que le serveur rappel de l'arrière n'a pas ce cookie de session, non plus vous devriez le partager (problème de sécurité) - même si le serveur pouvait faire l'appel avec un cookie spécifique
@Tseng, Ah OK, dans ce cas, cela ne fonctionnerait que si je vais utiliser certaines ressources partagées, pas la session. Mais c'était condamné depuis le début :)
@mortb, merci pour la recommandation. Je ferai refacteur dès que je trouve un moyen de le faire fonctionner avec l'application distante :)
La demande de votre application distante n'a rien à voir avec la demande initiale à votre application. Donc, il vous suffit de vous assurer que l'application distante ne répond que lorsque la demande de B est également effectuée.
Ah maintenant je vois, l'application distante rappelle à Controller_B
@mortb, exactement. J'ai donc trouvé un moyen, comme je l'ai posté ci-dessous. Peut-être pas le meilleur, mais ça marche.
Le rappel comprend-il une pièce d'identité? Sinon, plusieurs rappels simultanés peuvent déclencher la mauvaise réponse