Я хотел бы использовать Response.OnStarting
для выполнения некоторого кода, который использует шаблон асинхронного ожидания. Метод Response.OnStarting
определяется как
public void OnStarting(Func<Task> callback)
И я часто вижу, что он используется для изменения заголовков с помощью кода, подобного следующему:
context.Response.OnStarting( () => {
//modify the headers or do some synchronous work
});
Однако мне нужно выполнить некоторую асинхронную работу от делегата OnStarting. Допустим, метод, выполняющий асинхронную работу, объявлен следующим образом:
public Task DoWorkAsync() {
//write to a db or do something else async
return Task.CompletedTask;
}
Допустимо ли вызывать этот метод через делегат OnStarting, используя следующий подход?
context.Response.OnStarting(async () => {
await DoWorkAsync();
});
В Visual Studio это компилируется без предупреждений и, похоже, работает. Однако мне кажется странным, что метод Response.OnStarting
может использоваться как для синхронных, так и для асинхронных вызовов. Иногда мир асинхронного ожидания все еще заставляет меня немного почесать голову. Можете ли вы пролить свет на то, работает ли этот подход и почему? И почему Response.OnStarting
может использоваться с синхронизированным и асинхронным анонимным методом (если на самом деле это возможно)?
Обновление
Я немного покопался, чтобы посмотреть, смогу ли я найти код, который получает вызовы, передаваемые делегату методу OnStarting
.
Я обнаружил, что объект DefaultHttpRespose
содержит метод OnStarting
и внутри этого метода он в основном вызывает IHttpResponseFeature.OnStarting
, см. Здесь:
public override void OnStarting(Func<object, Task> callback, object state)
{
if (callback == null)
{
throw new ArgumentNullException(nameof(callback));
}
HttpResponseFeature.OnStarting(callback, state);
}
ссылка на исходный код
Но, что интересно, единственное место, где я могу найти реализацию IHttpResponseFeature.OnStarting
, это здесь с этим кодом:
void IHttpResponseFeature.OnStarting(Func<object, Task> callback, object state)
{
var register = Prop<Action<Action<object>, object>>(OwinConstants.CommonKeys.OnSendingHeaders);
if (register == null)
{
throw new NotSupportedException(OwinConstants.CommonKeys.OnSendingHeaders);
}
// Need to block on the callback since we can't change the OWIN signature to be async
register(s => callback(s).GetAwaiter().GetResult(), state);
}
Но эта реализация блокирует вызов асинхронного делегата. Есть даже комментарий на этот счет, но я не понимаю, почему это было необходимо? И я не уверен, что это реализация IHttpResponseFeature.OnStarting
, которая запускается, она только единственная, которую я смог найти на github. Любая помощь с благодарностью.