Оператор await имеет другое поведение в ASP.NET, чем в ASP.NET CORE?
В ASP.NET CORE 2.0 у меня такое поведение: я отправляю два запроса AJAX из браузера, первый запрос к одному действию (action1 это асинхронное действие) и второй запрос к другому действию (action2). Пока сервер обрабатывает первый запрос, второй запрос ставится в очередь, затем, когда первый запрос попадает в команду 1 "ожидание", действие 2 немедленно начинает обработку второго запроса, и первый запрос становится в очередь. И это ожидаемое поведение, но затем, если я попробую это в ASP.NET 4.6, у меня будет такое поведение: когда первый запрос попадает в инструкцию "await", второй запрос остается в очереди и должен ждать, пока первое действие не завершит все обработка, для второго действия, чтобы получить второй запрос.
Это мой код на стороне сервера
[HttpPost]
public async Task<JsonResult> LongRunningAction(HttpPostedFileBase file)
{
for (int i = 0; i < 100; i++)
{
await Task.Delay(300);
}
return Json("finish");
}
[HttpPost]
public ActionResult ParallelAction()
{
return this.Content("result");
}
Это мой JS:
startParallelRequest();
startLongRunningRequest()
function startLongRunningRequest(){
$.ajax(
{
url: "/mycontroller/LongRunningAction",
data: null,
processData: false,
contentType: false,
type: "POST",
success: function () {
stopParallelAction();
}
}
)
}
var intervalId;
function startParallelRequest() {
intervalId = setInterval(
function () {
$.ajax(
{
url: "/mycontroller/ParallelAction",
data: null,
processData: false,
contentType: false,
type: "POST",
success: function () {
}
}
);
},
1000
);
}
function stopParallelRequest() {
clearInterval(intervalId);
}
Я хочу получить ответ от параллельного действия в каждой итерации цикла. Такое поведение прекрасно работает в проекте ASP.NET 2.0, но не в ASP.NET 4.6. Заранее спасибо.
1 ответ
await
а также async
ключевые слова ведут себя одинаково. Но поведение этих ключевых слов зависит от SynchronizationContext. И разница в том, что ASP.NET Core не имеет контекста синхронизации.
Во всех случаях, await
возвращает управление вызывающей стороне и отправляет "продолжение" (своего рода делегат, указывающий на часть кода после await
) к SynchronizationContext.Current
, В ASP.NET (framework) это означает, что продолжения будут подбираться по одному, а не параллельно; в.NET Core они могут выполняться параллельно.
Это означает, что определенное поведение будет отличаться. Например, в.NET Framework вы можете легко взаимоблокировать себя, но многие из тех же вещей не будут взаимоблокироваться в ядре ASP.NET, потому что нет конкуренции для основного "потока" (на самом деле поток может переключаться из-за проворство, но по сути это однопоточное). С другой стороны, "потокобезопасный" код в.NET Framework может вызвать проблемы параллелизма в ядре.NET. Кстати, SynchronizationContext также отличается в приложениях Console и WinForms.
Действительно очень важно понимать SynchronizationContext при использовании async и await, и это будет зависеть от того, как и где будет выполняться код.
Смотрите также этот вопрос.