ASP.NET:是否可以异步调用任务在Global.asax中?(ASP.NET: Is it po

2019-07-30 01:10发布

我需要调用我在Global.asax中DB一些异步操作。 例如在Application_AuthenticateRequest我需要验证的是DB用户是否有可能与异步任务?

Answer 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调用该方法。



Answer 2:

我没有找到一个方法来使用新的C#的关键字异步和等待,但我们仍然可以使用APM模式使用异步操作在Global.asax中,因为它实现IHttpAsyncHandler接口。 这里是一个小的代码演示异步,这里我用一个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();
    }


Answer 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);
}

问题是的话,如何实现BeginAuthenticateRequestEndAuthenticateRequest使用新的异步/等待的C#的特征。 首先,让我们得到我们AuthenticateRequest的异步版本的方式进行:

private async Task AuthenticateRequestAsync(object sender, EventArgs args)
{
    // Yay, let's 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由任务实现的,所以你需要做的就是调用回调完成时。

最后一位是死很容易:

private void EndAuthenticateRequest(IAsyncResult result)
{
    // Nothing to do here.   
}


文章来源: ASP.NET: Is it possible to call async Task in Global.asax?