假设我的服务正在运行,并且我已使用代码在该服务中发送电子邮件通知。 " 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方法,例如在测试方法中使用?
答案 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#?(我的代码所基于的)