J'essaie d'écrire des méthodes d'assistance pour appeler de biztalk. BizTalk ne comprend pas les tâches ou async / attendre, de sorte que les méthodes d'assistant doivent renvoyer un type de retour normal .NET non soulevé dans une tâche Les méthodes d'assistance utilisent identitémodel.clients.ACTRÉDIRECTORY bibliothèque et ultérieurement httpclient pour appeler à un appel à un http- API basée sur la cache de ce résultat. Ces classes ne disposent que d'une API asynchrone, c'est-à-dire toutes les méthodes de retour de travail La façon dont BizTalk gère sa piscine de thread. que la piscine de thread sera saturée (à une valeur par défaut de 25 fils de travail) s'il existe une charge de message élevée; Par exemple, un grand nombre de fichiers ont été supprimés à la fois - il s'agit d'un scénario réalisable dans une utilisation normale et non un problème. Je l'ai observé via le débogage. P> Lorsque le code d'assistant fait un appel d'API, cela est assez coûteux car il renvoie beaucoup de données, et je veux seulement qu'un appel soit en cours à la fois. Si toute la mise en œuvre était synchrone, j'utiliserais simplement une instruction code> verroue code> autour de l'actualisation du cache, car le délai dans les messages de traitement est acceptable pour assurer la synchronisation. Le verrouillage a été démontré sur une impasse, ce qui a du sens pour moi, car l'architecture d'application garantit essentiellement qu'aucun thread ne sera disponible pour compléter les méthodes asynchrones. Il s'agit d'un cas plus extrême des conseils communément donnés de ne pas verrouiller dans le contexte du code asynchrone, en ce que ce n'est pas seulement probable mais certain à une impasse. P> J'ai essayé d'utiliser Le pseudocode suivant strong> (c.-à-d. N'essayez pas de vous corriger et de me corriger sur des problèmes de style de codage non pertinents pour le problème. Il ne peut aussi pas être un MCVE, sauf si vous avez une installation de BizTalk Handy) illustre le problème que j'essaie de résoudre: < / p>
Tâche
Semaphoreslim .WAITASYNC CODE> Pour activer l'équivalent au verrouillage, mais de manière non bloquante, c'est toujours empêcher plus d'un fil d'entrer dans le bloc, mais en leur permettant de générer au lieu de blocage. Cela ne résout pas le problème, car les méthodes d'assistance de niveau supérieur doivent toujours bloquer pour attendre la mise à jour du cache. Mon hypothèse est que le moment où cette attente donne le fil, il est ensuite avalé de traiter un nouveau message - qui le bloque ensuite, empêchant le fil entré dans le sémaphore de continuer. P>
3 Réponses :
Je dois dire d'abord, on dirait que vous créez beaucoup de problèmes inutiles en essayant de faire tout ce genre de fantaisie dans une classe d'assistance. Parce que A) Il n'y a vraiment pas de cas pratique pour les opérations asynchrones dans une classe d'assistance, car il ne changera pas de temps de traitement des messages, b) Vous devriez pas strud> appeler des points d'extrémités HTTP dans une classe d'assistance em>. p>
Donc, la solution correcte consiste à appeler le point d'extrémité HTTP à l'aide d'un port de livraison de livraison commandé fort>. p>.
Je dis ordonnai la livraison à cause de cela: "Et je veux seulement qu'un appel soit en cours à la fois", mais ... ça ne compte pas ce que tu veux em>, tu devrais Faites des appels série uniquement si le service le requiert ou a des problèmes de capacité. P>
Si vous souhaitez mettre en cache interne les résultats, il existe de nombreux exemples tels que celui-ci ici (toutes les règles .NET s'appliquent): Mixez la mise en cache pour vos applications BizTalk à l'aide de classes et méthodes statiques P>
Je suis d'accord avec vous et préférerais ne pas le faire de cette façon, mais ce n'est pas ma décision. Malheureusement, cela ne répond pas à la question.
@Tomw Alors comment pouvons-nous vous aider à démontrer que quiconque fait cette décision est faux? On dirait qu'ils ne comprennent pas comment Biztalk ou Async in .Net fonctionne. Et oui, cela répond à 100% à la question parce que vous ne devriez pas utiliser ce modèle dans Biztalk.
Mon point de vue est que c'est que c'est biztalk, et le fait que le travail lent est une demande d'API, est sans conséquence et la viande de la question est la pontage d'ASYNC avec des appels de méthode synchrones. Je pense qu'il devrait être possible de faire fonctionner le travail de synchronisation, le scénario exact n'est pas si important. J'ai ajouté ce détail parce que s'il était absent, quelqu'un se plaint, non pas parce que je pense que c'est du matériel au problème.
@Tomw Eh bien, oui, ce que vous voulez faire est très, très basique et très, très, très commun et biztalk, comme une plate-forme, fournit des méthodes, des modèles et des fonctionnalités à faire exactement cela. Vous choisissez de faire quelque chose de complètement inutile et, sur biztalk, mal. Pardon. C'est comme essayer d'utiliser ADO pour se connecter à Oracle dans une procédure stockée SQL Server ... Vous pouvez, mais c'est juste ... mal. Bonne chance, mais vous essayez de résoudre un problème que vous ou «architecte» créé.
Johns a raison, si vous devez appeler une classe d'assistance de Biztalk pour parler à un service Web, vous le faites mal. Vous perdrez toutes les capacités intégrées de biztalk telles que la gestion des erreurs, les tentatives automatiques, la persistance et la multi-threading.
@Dijkgraaf a accepté. Mais ce n'est pas la question que j'ai posée.
où étais-tu?! Aucune activité depuis le 1er juillet!
Votre question est en fait "Comment puis-je synchroniser-over-async lorsque la piscine de thread est saturée" et la seule réponse réelle est "Vous ne pouvez pas". Le problème avec synchronisation-over-async est qu'il bloque un thread, puis peut nécessiter un autre thread em> pour débloquer celui-là. Une chose que vous pouvez essayer est d'installer votre propre contexte (temporairement) sur votre fil. J'ai un Ceci permettra Malheureusement, vous ne pouvez pas garantir que cela fonctionnera toujours, car les continuations ne capturent que ce contexte par défaut em>. Et pour les bibliothèques générales telles que donc, le seul moyen d'éviter les blocages dans le code Sync-Overnc est de s'assurer que la piscine de thread n'est pas saturée. S'il y avait un moyen de limiter BizTalk à une certaine valeur et que la piscine de fil est plus grande que cela fonctionnerait. P> une solution beaucoup plus idéale serait d'aller "synchroniser tout le chemin". Vous voudriez remplacer Vous pourriez vous échapper avec une solution hybride: Utilisez Mais même si vous obtenez ce travail, cela n'est pas garanti à l'avenir. Manquant La seule solution vraiment garantie serait de forcer les API asynchrones à être synchrones, en écrivant votre propre webapi proxy qui enveloppe les appels asynccontext code> type dans mon bibliothèque Asyncex que peut le faire. Donc, à votre point d'entrée BizTalk, vous pouvez utiliser cela au lieu de bloquer directement: p>
attendre code> continuations à exécuter sur votre propre thread par défaut. Il se comporte un peu similaire à une boucle de message d'interface utilisateur (juste sans UI). P>
ActiveDirectory code> et
httpclient code>, le contexte de capture est considéré comme une mauvaise pratique; La plupart des codes de bibliothèque se déplacent d'utiliser la piscine de thread en utilisant toujours
configureawait (false) code>. p>
httpclient code> avec
webclient code>, mais à partir de votre description, il ressemble à
activedirectory code> ne prend pas en charge les API de synchronisation. P>
WebClient CODE> pour appeller l'API Synchrone et enveloppez tous les appels code> ActiveDirectory code> dans
asynccontext.run code >. Je pense que ceci pourrait em> travail car l'équipe ASP.NET CORE a supprimé la plupart / tous les
ConfigureAEAIT (FALSE) CODE> Appels dans leur code. Ainsi, l'API HTTP serait synchrone et le
activedirectory code> serait asynchrone mais avec ses continuations exécutées dans le fil qui l'attend (ne nécessitant pas de filetage de piscine de thread). P>
configureawait (FALSE) code> peut être considéré comme un "bogue", et s'ils "corrigent" le bug en ajoutant
configureawait (false) code> retour, alors votre code serait soumis Pour des blocages à nouveau. P>
ActiveDirectory code>. Ensuite, votre code BizTalk parlerait à cette API (et l'autre API) à l'aide de
WebClient code>, et tout le code BizTalk serait synchrone à ce point. P> p>
Merci! Cela confirme à peu près ce que je soupçonnais mais je ne voulais pas accepter. La seule idée ruinante restante pour moi est de savoir si ma compréhension de la gestion du thread de BizTalk est exacte, alors tout le monde en lisant - ne prenez pas ma parole pour cela. La nécessité d'utiliser des hacks pour faire de ce travail (de manière fiable ?!) suffit d'une justification de réécrire avec une approche différente.
Si le nombre de threads est le problème principal, vous pouvez réduire ou augmenter le nombre de threads en ajoutant l'adresse et le paramètre MaxConnection dans la section ConnectionMangement du fichier BTSNTSVC64.EXE.CONFIG ou BTSNTSVC.EXE.CONFIG s'il est 32 bits. Ou comme le dit Johns dans sa réponse, si vous le souhaitez, cochez la livraison ordonnée sur le port d'envoi.
<system.net> <connectionManagement> <add address="*" maxconnection="25" /> <add address="https://LIMITEDSERVER.com*" maxconnection="5" /> <add address="https://GRUNTYSERVER.com*" maxconnection="50" /> </connectionManagement> </system.net>
"Async tout le chemin" n'est pas une option, je suppose?
@Fildor Nope, pas aussi loin que je sache. Comme je l'ai mentionné la méthode publique à laquelle on parle ne peut pas être asynchronisé parce que l'appelant ne sait pas comment déballer cette tâche dans son résultat, comme le compilateur C #, le C # ne le fera jamais.
Avez-vous réussi à résoudre ce problème?