В настоящее время мы внедряем новую службу REST WCF в IIS для нашего сайта, и на некоторых страницах мы можем выполнять несколько вызовов AJAX с использованием JQuery в асинхронном режиме. Проблема в том, что кажется, что WCF (на стороне сервера) выполняется синхронно.
При загрузке страницы мы делаем 3 отдельных вызова для 3 разных методов. Используя логирование, я вижу, как все они попадают в файл global.asax в пределах 5 мс друг от друга Оттуда в журнале показывается все, что выполняется в порядке выхода из global.asax (не обязательно в порядке, в котором мы делали вызовы со страницы через javascript). Я ожидал, что каждый звонок получит собственную ветку и вернется индивидуально. Даже при подключении с помощью отладчика я вижу, что следующий метод не будет выполнен, пока я не перейду к текущему включенному методу.
Вот контракты на работу для трех методов, которые я «подумал», которые я реализовал для использования асинхронной модели.
[OperationContract(AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/ListUserPreferences"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginListUserPreferences(AsyncCallback callback, object state);
Result<List<Data.EnumerationItem<UserPreferenceType>>> EndListUserPreferences(IAsyncResult asyncResult);
[OperationContract(Name = "GetUserSecure", AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/GetUser"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginGetUser(AsyncCallback callback, object state);
Result<Data.User> EndGetUser(IAsyncResult asyncResult);
[OperationContract(AsyncPattern = true)]
[WebInvoke(
Method = "POST"
, UriTemplate = "/ListWithAttributes"
, BodyStyle = WebMessageBodyStyle.Wrapped
, ResponseFormat = WebMessageFormat.Json
, RequestFormat = WebMessageFormat.Json
)]
IAsyncResult BeginListWithAttributes(int index, int pageSize, AsyncCallback callback, object state);
Result<PagedCollection<Data.Attribute>> EndListWithAttributes(IAsyncResult asyncResult);
Вот пример одной из реализаций в сервисе.
public IAsyncResult BeginGetUser(AsyncCallback callback, object state)
{
var asyncResult = new CompletedAsyncResult<Result<Data.User>>(state);
asyncResult.Result = new Result<Data.User>();
asyncResult.Result.Value.UserId = Guid.Empty;
asyncResult.Result.Value.DisplayName = "asdfasd";
asyncResult.IsCompleted = true;
callback(asyncResult);
return asyncResult;
}
public Result<Data.User> EndGetUser(IAsyncResult asyncResult)
{
return ((CompletedAsyncResult<Result<Data.User>>)asyncResult).Result;
}
Вот атрибуты, которые мы имеем в классе реализации сервиса.
[AspNetCompatibilityRequirements(RequirementsMode = AspNetCompatibilityRequirementsMode.Allowed)]
[ServiceBehavior(InstanceContextMode = InstanceContextMode.PerCall, ConcurrencyMode = ConcurrencyMode.Multiple)]
Может ли кто-нибудь дать некоторое представление о том, почему они выполняются синхронно, и что мне нужно сделать, или, по крайней мере, указать мне, что нужно сделать, чтобы они выполнялись асинхронно?
UPDATE
Я взял ответ Мэтта и переместил свою логику в вызовы функции End и следовал за этой записью в блоге о том, как он сделал это более подробно Загрузка больших файлов в службу самообслуживания WCF . Однако я не мог заставить методы End вызывать его технику. Я также начинаю думать, что поступаю неправильно. Поскольку, просматривая журналы, моя пользовательская служба аутентификации выполняется перед каждым вызовом службы, что происходит до того, как какие-либо операции асинхронного метода даже сработают. После дальнейшего изучения я посмотрел на ThreadId каждого запроса, поступающего в IIS, а затем выполняющего операции. Похоже, что WCF использует только 1 рабочий поток ... точка. Не имеет значения, сколько запросов я отправляю за один раз в IIS. Например, если я отправляю 3 запроса, я вижу, что они все приходят в разное время (в пределах миллисекунд друг от друга) и все получают свой собственный поток. Но затем кажется, что WCF просто ставит их в очередь и выполняет их в таком порядке, потому что все они выполняются в одном потоке, включая вызовы службы аутентификации.