Ваш вопрос на самом деле «как мне выполнить синхронизацию по асинхронности, когда пул потоков заполнен», и единственный реальный ответ - «вы не можете».Проблема с синхронизацией по асинхронности заключается в том, что она блокирует поток, а затем может потребоваться другой поток, чтобы разблокировать этот поток.
Одна вещь, которую вы можете попробовать, - это установить собственный контекст (временно) в вашей теме.У меня есть AsyncContext
тип в моей AsyncEx библиотеке , которая может это сделать.Таким образом, в вашей точке входа в BizTalk вы можете использовать это вместо прямой блокировки:
// Old code:
// var result = MyLogicAsync().GetAwaiter().GetResult();
var result = AsyncContext.Run(() => MyLogicAsync());
Это позволит await
продолжениям работать в вашем собственном потоке по умолчанию.Он ведет себя подобно циклу сообщений в пользовательском интерфейсе (только без пользовательского интерфейса).
К сожалению, вы не можете гарантировать, что это всегда будет работать, потому что продолжения захватывают только этот контекст по умолчанию ,А для библиотек общего назначения, таких как ActiveDirectory
и HttpClient
, захват контекста считается плохой практикой;большая часть библиотечного кода старается изо всех сил использовать пул потоков, всегда используя ConfigureAwait(false)
.
Таким образом, единственный способ избежать взаимных блокировок в коде синхронизации по асинхронности - убедиться, что пул потоков не насыщен,Если бы был какой-то способ ограничить BizTalk каким-либо значением и иметь пул потоков больше этого, тогда это сработало бы.
Гораздо более идеальным решением было бы пойти "полностью синхронизировать".Вы хотели бы заменить HttpClient
на WebClient
, но из вашего описания это звучит так: ActiveDirectory
не поддерживает API синхронизации.
Возможно, вам не подходит гибридное решение: используйте WebClient
сделать синхронный вызов API и обернуть все ActiveDirectory
вызовы в AsyncContext.Run
.Я думаю, что может работать, потому что команда ASP.NET Core удалила большинство / все ConfigureAwait(false)
вызовов в своем коде.Таким образом, HTTP API будет синхронным, а ActiveDirectory
будет асинхронным, но его продолжения будут выполняться в ожидающем его потоке (не требуя потока пула потоков).
Но даже если вы получите этоработает, это не гарантировано в будущем.Отсутствие ConfigureAwait(false)
можно считать «ошибкой», и если они «исправят» ошибку, добавив ConfigureAwait(false)
обратно, то ваш код снова будет подвержен взаимоблокировкам.
Единственное действительно гарантированное решение будетчтобы заставить асинхронные API-интерфейсы быть синхронными, написав собственный прокси-сервер WebAPI, который упаковывает вызовы ActiveDirectory
.Тогда ваш код BizTalk будет взаимодействовать с этим API (и другим API), используя WebClient
, и весь код BizTalk будет синхронным в этот момент.