我正在使用 ASP.NET Web 窗体发送两封电子邮件,发送两封电子邮件后,我将从系统中删除该文件。我的代码使用 async/await,它在控制台应用程序中工作正常,但是当我将相同的代码移动到 asp.net web 表单时,它正在发送电子邮件,但在 Task.WaitAll(emailSender1, emailSender2) 之后我没有收到任何响应,结果,文件没有被删除,浏览器总是看到加载。我试图解决这个问题,但最终无法解决。我需要有人帮助解决问题或任何可以完成的替代方法。我的代码如下:
Default.aspx
<%@ Page Language="C#" AutoEventWireup="true" Async="true" CodeBehind="Default.aspx.cs" Inherits="WebApplication1.Default" %>
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head runat="server">
<title></title>
</head>
<body>
<form id="form1" runat="server">
<div>
<asp:Button ID="btnSendEmail" runat="server" Text="Send Email" OnClick="btnSendEmail_Click" />
</div>
</form>
</body>
</html>
Default.aspx.cs 代码隐藏
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private static string filePath = @"C:\Uploads\";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSendEmail_Click(object sender, EventArgs e)
{
Sender mailSender = new Sender();
mailSender.SendEmail("myfirstemail@gmail.com", "mysecondemail@gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Response.Redirect("Succcess.apsx");
}
}
}
Sender.cs
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace WebApplication1
{
public class Sender
{
public void SendEmail(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var emailSender1 = SendEmailAsync(toEmail, title, body, attachmentPath);
var emailSender2 = SendEmailAsync(logMail, "Copy of " + title, body, attachmentPath);
Task.WaitAll(emailSender1, emailSender2);
// deleting file
File.Delete(attachmentPath);
}
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
}
}
MailConfiguration.cs
public class MailConfiguration
{
private SmtpSection smtpSection = (ConfigurationManager.GetSection("system.net/mailSettings/smtp")) as SmtpSection;
public string ConfigurationFileName
{
get
{
try
{
return smtpSection.ElementInformation.Source;
}
catch (Exception)
{
return "";
}
}
}
public string FromAddress
{
get
{
return smtpSection.From;
}
}
public string Host
{
get
{
return smtpSection.Network.Host;
}
}
public int Port
{
get
{
return smtpSection.Network.Port;
}
}
public int TimeOut
{
get
{
return 2000;
}
}
public override string ToString()
{
return "From: [" + FromAddress + "] Host: [" + Host + "] Port: [" + Port + "]";
}
}
最佳答案
经过this article之后我开始知道控制台应用程序使用线程池 SynchronizationContext,而 GUI 或 ASP.NET 使用一次一个 block 的 SynchronizationContext。这意味着死锁的主要原因是 Task.WaitAll(emailSender1, emailSender2)。根据文章,我将这行代码更改为await Task.WhenAll(emailSender1, emailSender2)。更正的解决方案是:
Default.aspx.cs 代码隐藏
using System;
namespace WebApplication1
{
public partial class Default : System.Web.UI.Page
{
private static string filePath = @"C:\Uploads\";
protected void Page_Load(object sender, EventArgs e)
{
}
protected void btnSendEmail_Click(object sender, EventArgs e)
{
Sender mailSender = new Sender();
mailSender.SendEmail("myfirstemail@gmail.com", "mysecondemail@gmail.com", "Async mail with attachment", "Async mail with attachment body goes here ...", filePath + "TestFile.txt");
Response.Redirect("Success.aspx", false);
}
}
}
Sender.cs
using System;
using System.IO;
using System.Net.Mail;
using System.Text;
using System.Threading.Tasks;
namespace WebApplication1
{
public class Sender
{
public void SendEmail(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var result = ActualEmailSend(toEmail, logMail, title, body, attachmentPath);
}
public async Task ActualEmailSend(string toEmail, string logMail, string title, string body, string attachmentPath)
{
var emailSender1 = SendEmailAsync(toEmail, title, body, attachmentPath);
var emailSender2 = SendEmailAsync(logMail, "Copy of " + title, body, attachmentPath);
await Task.WhenAll(emailSender1, emailSender2);
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
File.Delete(attachmentPath);
}
}
public async Task SendEmailAsync(string toEmail, string title, string body, string attachmentPath)
{
try
{
// class to hold all values from the section system.net/mailSettings/smtp in app.config
MailConfiguration smtpSection = new MailConfiguration();
using (MailMessage mailMsg = new MailMessage("<" + smtpSection.FromAddress + ">", toEmail))
{
mailMsg.IsBodyHtml = true;
mailMsg.Subject = title;
mailMsg.SubjectEncoding = Encoding.UTF8;
mailMsg.Body = body;
mailMsg.BodyEncoding = Encoding.UTF8;
if (!string.IsNullOrWhiteSpace(attachmentPath) && File.Exists(attachmentPath))
{
Attachment attachment = new Attachment(attachmentPath);
mailMsg.Attachments.Add(attachment);
}
using (SmtpClient smtpClient = new SmtpClient())
{
smtpClient.Timeout = 1000000;
smtpClient.UseDefaultCredentials = false;
await smtpClient.SendMailAsync(mailMsg);
}
}
}
catch (Exception ex)
{
Console.WriteLine("SendEmail exception: " + ex);
}
finally
{
Console.WriteLine("SendEmail done");
}
}
}
}
关于c# - 始终使用异步/等待在 ASP.NET Web 窗体中的浏览器中加载页面,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45959443/