Мне нужно вызвать некоторые операции async в моей БД в Global.asax. например, в Application_AuthenticateRequest Мне нужно проверить подлинность пользователя с помощью DB Возможно ли это с помощью асинхронных задач?
ASP.NET: Можно ли вызвать async Task в Global.asax?
Ответ 1
Теперь есть более простой способ сделать это:
public MvcApplication()
{
var wrapper = new EventHandlerTaskAsyncHelper(DoAsyncWork);
this.AddOnAuthenticateRequestAsync(wrapper.BeginEventHandler, wrapper.EndEventHandler);
}
private async Task DoAsyncWork(object sender, EventArgs e)
{
var app = (HttpApplication)sender;
var ctx = app.Context;
...
await doSomethingAsync();
}
При таком подходе вы определяете метод с использованием ключевого слова async и переносите этот метод с использованием класса EventHandlerTaskAsyncHelper для генерации методов BeginEventHandler и EndEventHandler для перехода в вызов AddOnAuthenticateRequestAsync.
Ответ 2
Я не нашел способ использовать новое ключевое слово С# async и ждать, но мы все еще можем использовать шаблон APM для использования асинхронных операций в Global.asax, поскольку он реализовал интерфейс IHttpAsyncHandler. Вот небольшой код для демонстрации async, здесь я использую пример WebRequst, в вашем случае используйте операцию базы данных.
public Global()
{
this.AddOnAuthenticateRequestAsync(BeginGetAsyncData, EndGetAsyncData);
}
IAsyncResult BeginGetAsyncData(Object src, EventArgs args, AsyncCallback cb, Object state)
{
Console.WriteLine("BeginGetAsyncData: thread #" + System.Threading.Thread.CurrentThread.ManagedThreadId);
WebRequest request = WebRequest.Create("http://www.google.com");
return request.BeginGetResponse(cb, request); // call database async operation like SqlCommand.BeginExecuteReader()
}
void EndGetAsyncData(IAsyncResult ar)
{
Console.WriteLine("EndGetAsyncData: thread #" + System.Threading.Thread.CurrentThread.ManagedThreadId);
WebRequest requst = (WebRequest)ar.AsyncState;
System.Net.WebResponse response = requst.EndGetResponse(ar); // call database async operation like SqlCommand.EndExecuteReader()
Console.WriteLine(new StreamReader(response.GetResponseStream()).ReadToEnd());
response.Close();
}
Ответ 3
Вы должны добавить асинхронную версию AuthenticateRequest самостоятельно. Используя следующий код:
public MvcApplication()
{
// Contrary to popular belief, this is called multiple times, one for each 'pipeline' created to handle a request.
// Wire up the async authenticate request handler.
AddOnAuthenticateRequestAsync(BeginAuthenticateRequest, EndAuthenticateRequest, null);
}
Проблема заключается в том, как реализовать BeginAuthenticateRequest
и EndAuthenticateRequest
, используя новые функции async/await С#. Во-первых, позвольте получить нашу асинхронную версию AuthenticateRequest:
private async Task AuthenticateRequestAsync(object sender, EventArgs args)
{
// Yay, let do async stuff!
await ...
}
Теперь нам нужно выполнить реализацию BeginAuthenticateRequest и EndAuthenticateRequest. Я последовал за сообщением в блоге, но получил свою собственную реализацию:
private IAsyncResult BeginAuthenticateRequest(object sender, EventArgs args, AsyncCallback callback, object state)
{
Task task = AuthenticateRequestAsync(sender, args);
var tcs = new TaskCompletionSource<bool>(state);
task.ContinueWith(_ =>
{
if (task.IsFaulted && task.Exception != null) tcs.TrySetException(task.Exception.InnerExceptions);
else if (task.IsCanceled) tcs.TrySetCanceled();
else tcs.TrySetResult(true);
if (callback != null) callback(tcs.Task);
}, CancellationToken.None, TaskContinuationOptions.None, TaskScheduler.Default);
return tcs.Task;
}
Вы можете прочитать всю связанную статью, чтобы увидеть, как она работает, но в основном IAsyncResult
реализуется Task, поэтому все, что вам нужно сделать, это вызвать обратный вызов, когда закончите.
Последний бит мертв легко:
private void EndAuthenticateRequest(IAsyncResult result)
{
// Nothing to do here.
}