C#异步任务-MANDRILL API

本文关键字:API -MANDRILL 任务 异步 | 更新日期: 2023-09-27 18:22:03

我正在为我们的内部系统设置Mandrill Api。

我可以让API正常工作,并可以从中接收电子邮件,我的问题是,当我尝试从发送请求中获得结果时,系统会无限期挂起。

我的代码如下:

public async Task<bool> SendEmail(MandrillSendTemplateRequest request)
{
    var result = await _mandrill.SendMessageTemplate(Map(request));
    return result[0].Status.ToString() == "sent";
}

如果我在没有返回的情况下运行上面的代码,那么电子邮件会发送罚款。如果我运行上面的代码并返回,那么电子邮件发送良好,但我的程序只是挂起。

有人能阐明这个问题吗?

编辑。作为参考,我使用的是NuGet Packages的Shawn Mclean的Mandrill.Net Wrapper。Mandrill API 2.2.7

编辑。调用SendEmail方法的按钮点击事件:

  Private Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
    Try
        WaitCursor = True
        Dim mgr As New CustomerCommunicationsManager()
        Dim r As New MandrillSendTemplateRequest()
        Dim m As New MandrillMessage()
        m.FromEmail = "from@icloud.com"
        m.FromName = "fromName"
        m.Subject = "Test"
        m.ForeName = "Software"
        m.Surname = "Dept"
        m.EmailAddress = "software@icloud.com"
        r.Message = m
        r.TemplateName = "WelcomeBasic"
        Dim sent As Boolean = mgr.Mandrill.SendEmail(r).Result
    Catch ex As Exception
    Finally
        WaitCursor = False
    End Try

End Sub

编辑。地图代码(请求)(发送电子邮件方式)

private SendMessageTemplateRequest Map(MandrillSendTemplateRequest obj)
{
    if (obj == null) { return null; }
    return new SendMessageTemplateRequest(Map(obj.Message), obj.TemplateName, Map(obj.TemplateContent));
}
private EmailMessage Map(MandrillMessage obj)
{
    if (obj == null) { return null; }
    return new EmailMessage
    {
        AutoHtml = obj.AutoHtml,
        AutoText = obj.AutoText,
        FromEmail = obj.FromEmail,
        FromName = obj.FromName,
        Important = obj.Important,
        PreserveRecipients = obj.PreserveRecipients,
        Subject = obj.Subject,
        Tags = obj.tags,
        To = new EmailAddress[] { new EmailAddress(obj.EmailAddress, obj.FullName) },
        TrackOpens = obj.TrackOpens,
        TrackClicks = obj.TrackClicks
    };
}
private IEnumerable<TemplateContent> Map(IEnumerable<MandrillTemplateContent> obj)
{
    if (obj == null) { return null; }
    List<TemplateContent> content = new List<TemplateContent>();
    foreach (MandrillTemplateContent c in obj)
    {
        content.Add(new TemplateContent{ Content = c.Content, Name = c.Name });
    }
    return content;
}

C#异步任务-MANDRILL API

您有一个死锁,因为您在UI线程的上下文中阻塞了异步方法。你不应该阻止异步代码,你应该等待它:

Private Async Sub btnTest_Click(sender As Object, e As EventArgs) Handles btnTest.Click
...
        Dim sent As Boolean = Await mgr.Mandrill.SendEmail(r)
End Sub

UI线程有一个SynchronizationContext(您可以看到SynchronizationContext.Current != null),它确保等待后的代码被发布到单个UI线程。

由于您使用Task.Result阻塞了UI线程,等待之后的代码无法运行,这意味着任务无法完成,因此UI线程将永远阻塞。

您可以通过告诉等待者不要使用ConfigureAwait(false)捕获SynchronizationContext来减轻这种情况,但尽管这是一个很好的做法,但您不应该一开始就阻止:

public async Task<bool> SendEmailAsync(MandrillSendTemplateRequest request)
{
    var result = await _mandrill.SendMessageTemplate(Map(request)).ConfigureAwait(false);
    return result[0].Status.ToString() == "sent";
}