简体   繁体   English

在非异步方法中调用异步并记录异步await方法的异常

[英]call async in non async method and log exceptions for the async await method

Suppose my service is runing and i have used a code for sending email notification in that service. 假设我的服务正在运行,并且我已使用代码在该服务中发送电子邮件通知。 The "EmailNotification" method is async and await. “EmailNotification”方法是异步并等待。

Code of EmailNotification: 电子邮件通知代码:

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

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

            }
        }

Used EmailNotification methos in my some test method like that: 在我的一些测试方法中使用的EmailNotification方法如下:

public void test()
        {
        EmailNotification();
        }

My Problem: 我的问题:

1)How can i log execptions of async and await method if my destination method test is not of type async? 1)如果我的目标方法测试不是async类型,我如何记录async和await方法的execptions?

2)Is it possible to use async method in non async type like above ia m using in test method? 2)是否可以在非同步类型中使用异步方法,如在测试方法中使用?

How can i log execptions of async and await method if my destination method test is not of type async? 如果我的目标方法测试不是async类型,我如何记录async和await方法的execptions?

The task returned from the async method will contain any exceptions from that method. async方法返回的任务将包含该方法的任何异常。 However, calling it in a "fire and forget" manner such as this means that the returned task is ignored. 但是,以“即发即忘”的方式调用它,例如这意味着忽略返回的任务。 So, you'll have to have a try / catch in your async method (which is already there) and log in the catch . 因此,您必须在async方法(已经存在)中使用try / catch并登录catch

Is it possible to use async method in non async type like above ia m using in test method? 是否可以在非同步类型中使用async方法,如上所述,在测试方法中使用?

Possible? 可能? Sure, it'll compile and run. 当然,它会编译运行。

A good idea? 一个好主意? Probably not. 可能不是。

On ASP.NET, any work done outside of an HTTP request is not guaranteed to complete. 在ASP.NET上,不保证在HTTP请求之外完成的任何工作都可以完成。 When your code calls EmailNotification , it is starting some work and then completing the HTTP request (by sending a response). 当您的代码调用EmailNotification ,它会开始一些工作,然后完成HTTP请求(通过发送响应)。 That send-email work is then done without an HTTP request, and may be lost if your app is recycled. 然后,在没有HTTP请求的情况下完成发送电子邮件工作,如果您的应用程序被回收,则可能会丢失。

This is a fine approach if you're perfectly OK with emails disappearing occasionally without any logs or any other indicators that something went wrong. 这是一个很好的方法,如果你完全没有电子邮件偶尔消失没有任何日志或任何其他指标出错。 If you're not OK with that, then you'll need a more robust solution (such as a proper distributed architecture , as I describe on my blog). 如果您对此不满意,那么您将需要一个更强大的解决方案(例如我在博客上描述的适当的分布式架构 )。 Or you can just outsource that part of it by using an email service such as SendGrid. 或者您可以通过使用SendGrid等电子邮件服务将其中的一部分外包出去。

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

And then use it like this: 然后像这样使用它:

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

Alternatively: 或者:

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

You should always try to use await / async all the way, and avoid this pattern when possible. 您应该始终尝试使用await / async ,并尽可能避免使用此模式。 But when you need to call an async method from a non-async method you can use GetAwaiter().GetResult() in order to await the task and also get the correct Exception (if any). 但是当你需要从非异步方法调用异步方法时,可以使用GetAwaiter().GetResult()来等待任务并获得正确的异常(如果有的话)。

As mentioned in the comments there's already an excellent answer from Stephen Cleary in this question: How to call asynchronous method from synchronous method in C#? 正如评论中所提到的, Stephen Cleary已经在这个问题中得到了很好的答案: 如何从C#中的同步方法调用异步方法? (which my code is based on) (我的代码基于)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM