【问题标题】:Function returns before await async finishes函数在等待异步完成之前返回
【发布时间】:2020-02-06 15:13:57
【问题描述】:

我正在尝试通过 SendGrid API 发送 2 封电子邮件。有时0发送,有时1发送,有时都发送。似乎该功能不等待承诺。我该如何解决它,以便它始终发送两封电子邮件?

我的函数如下所示:

private async Task<bool> SendMails(string email, string name, string pdfPath, string imgPath)
{
    var client = new SendGridClient(_config["SendGrid:Key"]);
    bool messagesSent = false;
    var messageClient = new SendGridMessage
    {
        From = new EmailAddress(_config["SendGrid:Recipient"]),
        Subject = "Testmail",
        HtmlContent = _textManager.Get("getMailHtml")
    };

    var messageSecondClient = new SendGridMessage
    {
        From = new EmailAddress(_config["SendGrid:Recipient"]),
        Subject = "Second Testmail",
        HtmlContent = _textManager.Get("getSecondMailHtml")
    };

    messageClient.AddTo(email, name);
    messageSecondClient.AddTo(email, name);

    string[] fileListClient = new string[] { pdfPath };
    string[] fileListSecond = new string[] { pdfPath, imgPath };

    foreach (var file in fileListClient)
    {
        var fileInfo = new FileInfo(file);

        if (fileInfo.Exists)
            await messageClient.AddAttachmentAsync(fileInfo.Name, fileInfo.OpenRead());
    }

    foreach (var file in fileListSecond)
    {
        var fileInfo = new FileInfo(file);

        if (fileInfo.Exists)
            await messageSecondClient.AddAttachmentAsync(fileInfo.Name, fileInfo.OpenRead());
    }

    var responseClient = await client.SendEmailAsync(messageClient);
    var responseSecond = await client.SendEmailAsync(messageSecondClient);

    if (responseClient.StatusCode.ToString() == "202" && responseSecond.StatusCode.ToString() == "202")
    {
        messagesSent = true;
    }
    return messagesSent;
}

我就是这样称呼它的:

            Task<bool> sendMails = await Task.FromResult(SendMails(formCollection["email"], formCollection["name"], pdfPath, imgPath));

            if (!sendMails.Result)
            {
                errorMessage = "Error sending mails.";
            }

【问题讨论】:

  • 删除Task.FromResult(...)。直接在 SendMails 上调用它:var isSent = await SendMails(...).
  • @Silvermind 我想要结果布尔值以捕获错误。如果我删除 TaskResult,我无法取回返回值。有没有其他方法可以查看返回值?
  • 并确保调用SendMails的方法被标记为异步,并确保调用that的方法被标记为异步并等待调用。以此类推,一直到调用堆栈。
  • 可以得到异步调用的结果。 bool myResult = await SendMails(/* params*/);
  • 另外,请注意 SendGrid 的邮件系统是一个队列,因此,您正在执行的任务只会导致 SendGrid 队列中的条目。现在他们处理队列的速度非常快,但仍然会不时发生,您会注意到发送之间的轻微延迟。在我看来,这正在发生。

标签: c# .net asynchronous async-await sendgrid


【解决方案1】:

您正在阻止异步任务:

if (!sendMails.Result)

这可以cause a deadlock。不要阻塞,而是使用await

而且你还可以去掉await Task.FromResult,其中isn't doing anything at all

bool sentMails = await SendMails(formCollection["email"], formCollection["name"], pdfPath, imgPath);

if (!sentMails)
{
  errorMessage = "Error sending mails.";
}

【讨论】:

  • @JohnathanBarclay:在操作的代码中,从sendMails 返回的任务可能在调用Result 时完成,也可能未完成。遍历调用,特别注意 FromResult 调用的返回类型,您应该会发现问题。
  • 这确实花了我一分钟...我想我以前从未见过传递给await Task.FromResult任务。 :)
【解决方案2】:

Task.FromResult 返回一个已完成的 Task,而不是从SendMails 返回的Task

没有什么在等待SendMails 的完成。

等待方法返回的Task

bool result = await SendMails(formCollection["email"], formCollection["name"], pdfPath, imgPath);

await 关键字为您解开 Task.Result

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-06-17
    • 1970-01-01
    • 2017-08-04
    • 2021-12-02
    • 2020-03-02
    相关资源
    最近更新 更多