在非异步方法中调用异步并记录异步等待方法

时间:2016-06-13 05:08:59

标签: c# asp.net asp.net-mvc async-await

假设我的服务正在运行,并且我已使用代码在该服务中发送电子邮件通知。 " EmailNotification"方法是异步并等待。

电子邮件通知代码:

public async task EmailNotification()
        {
            try
            {
            //code here

             using (SmtpClient smtp = new SmtpClient())
                    {
                        //mail sending 
                     await smtp.Send(mailMessage);
                    }
            }
            Catch(Exception ex)
            {

            }
        }

在我的测试方法中使用的EmailNotification方法如下:

public void test()
        {
        EmailNotification();
        }

我的问题:

1)如果我的目标方法测试不是async类型,我如何记录async和await方法的执行?

2)是否可以在非同步类型中使用async方法,例如在测试方法中使用?

2 个答案:

答案 0 :(得分:2)

  

如果我的目标方法测试不是async类型,我如何记录async和await方法的执行?

async方法返回的任务将包含该方法的任何异常。然而,在火灾中召唤它并忘记"这样的方式意味着忽略返回的任务。因此,您必须在try方法(已经存在)中使用catch / async并登录catch

  

是否可以在非同步类型中使用async方法,例如在测试方法中使用?

可能?当然,它会编译并运行。

一个好主意?可能不是。

在ASP.NET上,无法保证完成在HTTP请求 之外完成的任何工作。当您的代码调用EmailNotification时,它开始一些工作,然后完成HTTP请求(通过发送响应)。然后,在没有HTTP请求的情况下完成发送电子邮件工作,如果您的应用程序被回收,则可能会丢失。

这是一个很好的方法,如果你完全没问题,电子邮件偶尔会消失,没有任何日志或任何其他迹象表明出现了问题。如果您对此不满意,那么您需要一个更强大的解决方案(例如我在我的博客中描述的proper distributed architecture)。或者您可以使用SendGrid等电子邮件服务将其中的一部分外包出去。

答案 1 :(得分:1)

public static class TaskExtensions
{
    /// <summary>
    /// Waits for the task to complete, unwrapping any exceptions.
    /// </summary>
    /// <param name="task">The task. May not be <c>null</c>.</param>
    public static void WaitAndUnwrapException(this Task task)
    {
        task.GetAwaiter().GetResult();
    }

    /// <summary>
    /// Waits for the task to complete, unwrapping any exceptions.
    /// </summary>
    /// <param name="task">The task. May not be <c>null</c>.</param>
    public static T WaitAndUnwrapException<T>(this Task<T> task)
    {
        return task.GetAwaiter().GetResult();
    }
}

然后像这样使用它:

try
{
    var t = EmailNotification();
    t.WaitAndUnwrapException();
}
catch(Exception ex)
{
   // log...
}

可替换地:

public void test()
{
    try
    {
        var t = EmailNotification();
        t.GetAwaiter().GetResult();
    }
    catch(Exception ex)
    {
        // Do your logging here
    }
}

您应该始终尝试使用await / async,并尽可能避免使用此模式。但是当你需要从非异步方法调用异步方法时,可以使用GetAwaiter().GetResult()来等待任务并获得正确的异常(如果有的话)。

正如评论中所提到的,Stephen Cleary在这个问题中已经有了很好的答案: How to call asynchronous method from synchronous method in C#?(我的代码所基于的)