使用Task.Run代替Delegate.BeginInvoke [英] Use Task.Run instead of Delegate.BeginInvoke

查看:2475
本文介绍了使用Task.Run代替Delegate.BeginInvoke的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近升级我的项目,ASP.NET 4.5和我一直在等待很长时间才能使用4.5的异步功能。阅读文档后,我不知道我是否能在所有提高我的code。

I have recently upgraded my projects to ASP.NET 4.5 and I have been waiting a long time to use 4.5's asynchronous capabilities. After reading the documentation I'm not sure whether I can improve my code at all.

我想要异步执行一个任务,然后忘掉它。我目前这样做的方法是创建委托,然后用的BeginInvoke

I want to execute a task asynchronously and then forget about it. The way that I'm currently doing this is by creating delegates and then using BeginInvoke.

下面是我的项目中的过滤器之一,在我们的数据库中的每个用户访问必须被审计资源时创建一个审计:

Here's one of the filters in my project with creates an audit in our database every time a user accesses a resource that must be audited:

public override void OnActionExecuting(ActionExecutingContext filterContext)
{
    var request = filterContext.HttpContext.Request;
    var id = WebSecurity.CurrentUserId;

    var invoker = new MethodInvoker(delegate
    {
        var audit = new Audit
        {
            Id = Guid.NewGuid(),
            IPAddress = request.UserHostAddress,
            UserId = id,
            Resource = request.RawUrl,
            Timestamp = DateTime.UtcNow
        };

        var database = (new NinjectBinder()).Kernel.Get<IDatabaseWorker>();
        database.Audits.InsertOrUpdate(audit);
        database.Save();
    });

    invoker.BeginInvoke(StopAsynchronousMethod, invoker);

    base.OnActionExecuting(filterContext);
}

但是,为了完成这个异步任务,我需要时刻定义一个回调,它看起来像这样:

But in order to finish this asynchronous task, I need to always define a callback, which looks like this:

public void StopAsynchronousMethod(IAsyncResult result)
{
    var state = (MethodInvoker)result.AsyncState;
    try
    {
        state.EndInvoke(result);
    }
    catch (Exception e)
    {
        var username = WebSecurity.CurrentUserName;
        Debugging.DispatchExceptionEmail(e, username);
    }
}

我宁可不使用回调都由于这样的事实,我不需要从我异步调用的任务的结果。

I would rather not use the callback at all due to the fact that I do not need a result from the task that I am invoking asynchronously.

我怎样才能改善这种code与 Task.Run()(或异步等待)?

How can I improve this code with Task.Run() (or async and await)?

推荐答案

如果我理解您的要求正确,你想揭开序幕任务,然后忘掉它。任务完成后,如果发生异常,要记录它。

If I understood your requirements correctly, you want to kick off a task and then forget about it. When the task completes, and if an exception occurred, you want to log it.

我会使用 Task.Run 以创建一个任务,然后按 ContinueWith 附上的后续任务的。这延续任务将记录从父任务抛出的任何异常。此外,使用 TaskContinuationOptions.OnlyOnFaulted ,以确保继续只运行的如果的发生了异常。

I'd use Task.Run to create a task, followed by ContinueWith to attach a continuation task. This continuation task will log any exception that was thrown from the parent task. Also, use TaskContinuationOptions.OnlyOnFaulted to make sure the continuation only runs if an exception occurred.

Task.Run(() => {
    var audit = new Audit
        {
            Id = Guid.NewGuid(),
            IPAddress = request.UserHostAddress,
            UserId = id,
            Resource = request.RawUrl,
            Timestamp = DateTime.UtcNow
        };

    var database = (new NinjectBinder()).Kernel.Get<IDatabaseWorker>();
    database.Audits.InsertOrUpdate(audit);
    database.Save();

}).ContinueWith(task => {
    task.Exception.Handle(ex => {
        var username = WebSecurity.CurrentUserName;
        Debugging.DispatchExceptionEmail(ex, username);
    });

}, TaskContinuationOptions.OnlyOnFaulted);

在ASP.NET

作为一个侧面说明,后台任务和发射后不管是场景的的劝阻。见<一href=\"http://haacked.com/archive/2011/10/16/the-dangers-of-implementing-recurring-background-tasks-in-asp-net.aspx/\">The实施定期后台任务在ASP.NET 的危害

As a side-note, background tasks and fire-and-forget scenarios in ASP.NET are highly discouraged. See The Dangers of Implementing Recurring Background Tasks In ASP.NET

这篇关于使用Task.Run代替Delegate.BeginInvoke的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆